Let the method accept any type of data in C #

I have a lot of unit tests that pretty much test the same behavior. However, the data type is changing.

I am trying to create a universal method that can accept any type of data. I tried to make my var input parameter, but this is not allowed. Also reviewed by C # generics, but usually deals with a list.

+15
c # tdd
May 04 '11 at 16:44
source share
5 answers

You can make a object parameter:

 public void DoSomething(object arg) { //... 

Or you could do what I prefer and make a general method:

 public void DoSomething<T>(T arg) { //... 

The general approach has two main advantages, and I will give examples of why they are useful:

  • Even if you do not explicitly specify the arg type, you still have access to it.
  • You can add restrictions on the types you want to allow.

Conversely, the object approach has some important drawbacks:

  • Since you are handling arg as an object , you can do what you can do with any object.
  • If you pass the value type as the object parameter, the variable will be boxed , which means a performance hit. This is not a huge blow, but if you call DoSomething several thousand times in a row, you can start to feel it.

General and typical limitations

Adding a type constraint to the general method allows you to restrict the method so that it accepts only certain types. Why is this useful? Because, although you do not know or do not care about which particular type you are working with, you now know something about it, and you can use this information.

Consider the following setup:

 public interface IAnimal { void Move(); } public class Duck : IAnimal { public void Move() { Console.WriteLine("Flying"); } } public class Fish : IAnimal { public void Move() { Console.WriteLine("Swimming"); } } public class Ant : IAnimal { public void Move() { Console.WriteLine("Walking"); } } 

Since we have an IAnimal interface, we can write generic methods that target any IAnimal implementation:

 public class Program { static void DoMove<T>(T animal) where T : IAnimal { animal.Move(); } public static void Main(string[] args) { Duck duck = new Duck(); Fish fish = new Fish(); Ant ant = new Ant(); DoMove<Duck>(duck); DoMove<Fish>(fish); DoMove<Ant>(ant); } } 

Run it: http://rextester.com/GOF1761

When we write the DoMove method, we donโ€™t care whether its parameter is animal Duck , a Fish , a Ant or something else. All we care about is animal.Move() . Since we used the where T : IAnimal , the compiler knows everything we need to know:

  • The variable animal is of type T
  • Regardless of T , it implements IAnimal .
  • Everything that implements IAnimal has a Move() method.
  • Therefore, we can safely call animal.Move() .

(By the way, yes, we could just write DoMove as static void DoMove(IAnimal animal) , but that's another discussion.)

Type inference (and some of its consequences)

Ok, but let's take one more step. In many cases, you can call common methods without specifying their type parameters. This is called the type of output , and, in addition to saving a certain set of text, it can be useful when performing the same operation on objects of different types.

 public static void Main(string[] args) { IAnimal[] animals = new IAnimal[] { new Duck(), new Fish(), new Ant() }; foreach (IAnimal animal in animals) { DoMove(animal); } } 

Run it: http://rextester.com/OVKIA12317

You only need to write the DoMove<T> method DoMove<T> , and you can call it on any type of IAnimal without specifying a more specific type. The corresponding version of Move will be called every time, because DoMove<T> can infer which type to use for T When you call DoMove(duck) , .NET understands that you really mean DoMove<Duck>(duck) , which then calls the Move method in the Duck class.

+31
May 04 '11 at 16:58
source share

You can take object as a parameter type. Better still would be to use generics:

 void MyMethod<T>(T parm) { ... } 

Thus, this parameter actually refers to the type that the user passed - it does not fit into the box, for example, using object and value types.

+7
May 4 '11 at 4:47 pm
source share
 void MyTestMethod<T>(T t) { } 

gives you a general testing method, but I canโ€™t imagine how this could be useful. What do you need to check? How do you know type T has these methods? T can be any type in the above method. The only methods you can call from T in the above example are the general methods of object .

What you really need to do is define the general behavior against one or more types that you want to test, and define the syntactic contract of this behavior through the interface. You can then limit your general testing method to accept only those types that implement this interface.

 interface IMyInterface { void DoSomething(); } void MyTestMethod<T>(T t) where T : IMyInterface { t.DoSomething(); } 
+4
May 04 '11 at 16:56
source share
 public void YourMethod<T>(T parameter) { } 
+3
May 04 '11 at 16:46
source share

try using a dynamic keyword, this will work provided that all of your different types have the same methods that your unit tests use, otherwise you will get an exception at runtime

0
May 4 '11 at 16:50
source share