Let method take any data type in c#

You could make the parameter an object:

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

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

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

The generic approach has two major advantages, and I'll give examples of why they're useful:

  1. Even though you don't explicitly specify the type of arg, you still have access to it.
  2. You can add constraints on the types you want to allow.

Conversely, the object approach has some important disadvantages:

  1. Since you're treating arg as an object, you'll only be able to do things you could do with any object.
  2. If you pass a value type as an object parameter, the variable will be boxed, which means a performance hit. It's not a huge hit, but if you call DoSomething several thousand times in a row, you might start feeling it.

Generics and Type Constraints

Adding a type constraint to a generic method allows you to restrict the method so that it only accepts certain types. Why is that useful? Because even though you don't know—or care—what specific type you're working with, you now know something about it, and you can use that 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 targeting any implementation of IAnimal:

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 animal is a Duck, a Fish, an Ant, or anything else. All we care about is calling animal.Move(). Since we used the where T : IAnimal constraint, the compiler knows everything we need it to know:

  1. The variable animal is of type T.
  2. Whatever T is, it implements IAnimal.
  3. Anything that implements IAnimal has a Move() method.
  4. 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 implications)

Fine, but let's take it a step further. In many cases, you can call generic methods without having to specify their type parameters. This is called type inference, and aside from saving you some typing, it can be useful when doing 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 have to write the DoMove<T> method once, and you can call it on any type of IAnimal without having to give a more specific type. The appropriate version of Move will be called each time, because DoMove<T> is able to 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 on the Duck class.


You can take in object as a parameter type. Even better, perhaps, would be to use generics:

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

This way the parameter is actually of the type the user passed in -- it isn't boxed like with object and value types.


void MyTestMethod<T>(T t) { }

gets you a generic test method, but I can't imagine any way that could be useful. What do you need to test? How do you know type T has those methods? T can be any type in the above method. The only methods you can call from t in the above example are the common methods of object.

What you really need to do is identify a common behaviour against one or more types which you want to test, and define the syntactical contract of that behaviour through an interface. You can then constrain your generic test method to only accept types which implement that interface.

interface IMyInterface
{
    void DoSomething();
} 

void MyTestMethod<T>(T t) where T : IMyInterface
{ 
    t.DoSomething();
}

Tags:

C#

.Net

Tdd