tags:

views:

269

answers:

7

Hey all!

I was wondering if the following is possible. Create a class that accepts an anonymous type (string, int, decimal, customObject, etc), then have overloaded methods that do different operations based on the Type. Example

    class TestClass<T>
{
  public void GetName<string>()
  {
      //do work knowing that the type is a string    
  }

  public string GetName<int>()
  {
      //do work knowing that the type is an int

  } 

  public string GetName<int>(int addNumber)
  {
      //do work knowing that the type is an int (overloaded)    
  } 

  public string GetName<DateTime>()
  {
      //do work knowing that the type is a DateTime

  } 

  public string GetName<customObject>()
  {
      //do work knowing that the type is a customObject type    
  }

}

So now I could call the GetName method, and because I already passed in the type when I initialized the object, the correct method is found and executed.

TestClass foo = new TestClass<int>();

//executes the second method because that's the only one with a "int" type
foo.GetName();

Is this possible or am I just dreaming?

A: 

Would using class extension methods work for you?

You can essentially add methods to the classes you want, and then you can call it the same way.

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int GetName(this String str)
        {
            ...
        }
    }   
}

called using:

myString.GetName();
CookieOfFortune
+3  A: 

"Specialization" is not possible in C# the way it is in C++. In .NET generics, a generic class or method of <T> must be the same for all possible values of T. This allows the runtime to do an optimization that two different reference types, say TestClass<string> and TestClass<List<int>>, share the same machine language code. (different value types get separate machine code, but you still can't specialize.)

I find it sometimes helps to create a generic interface or base class like this:

abstract class Base<T> {
  public abstract T GetName();
  // any common code goes here that does not require specialization
}

And do specialization in derived classes:

class IntVersion : Base<int> {
  public override int GetName() { return 1; }
  public int GetName(int addNumber) { ... }
}
class StringVersion : Base<string> {
  public override string GetName() { return "foo"; }
}
class DateTimeVersion : Base<DateTime> {
  public override DateTime GetName() { return DateTime.Now; }
}
Qwertie
+1 Generics != Templates
sixlettervariables
+1  A: 

No, this is not possible. What you are trying to do is similar to template specialization in C++, which is (sadly) not possible in C#.

You need to if/else or switch on

typeof(T)

to invoke specialized implementations.

However, you can constraint the type of T to be either a class (reference Value) or struct (value) or subclass of a certain baseclass like so:

 public Foo<T> DoBar<T>() where T : FooBase;
Johannes Rudolph
A: 

c# doesn't have support for such dispatching.

and this is not right way for doing method overloading also (Error'TestClass' already defines a member called 'GetName' with the same parameter types) as long as all inside <> is not a part of method signature.

Trickster
+6  A: 

What you're trying to do is possible like this:

class TestClass<T>
{
   public string GetName<T>()
   {
      Type typeOfT = typeof(T);
      if(typeOfT == typeof(string))
      {
          //do string stuff
      }
   }
}

While this is possible, you're kind of defeating the purpose of generics. The point of generics is when the type doesn't matter, so I don't think generics is appropriate in this case.

BFree
+2  A: 

Specialization is not possible in C#. The closest thing in C# is the following

public void Example() {
  public static void Method<T>(T value) { ... }
  public static void Method(int value){ ... }
  public static void Method(string) { ... }
}

The C# compiler will prefer a non-generic method over a generic method. This means that calling with an int paramater will bind to the int overload vs. the generic one.

Example.Method(42);  // Method(int)
Example.Method(new Class1())  // Method<T>(T)

This will bite you though because this does not apply when the method is called generically. In that case it will bind to the generic overload no matter the type.

public void Gotcha<T>(T value) {
  Example.Method(value);
}

Gotcha(42);  // Still calls Example.Method<T>()
JaredPar
A: 

If you need to do type-specific work in your class, then your class is not generic. You should probably make a seperate class for each type you want to handle. If there is some functionality that does have a proper reason for being generic, you can put it in an common base class.

An example:

abstract class TestClass<T>
{
    public List<T> Items { get; set; }

    // other generic (i.e. non type-specific) code
}

class IntTestClass : TestClass<int>
{
    public string GetName()
    {
        // do work knowing that the type is an int
    }

    // other code specific to the int case
}

class StringTestClass : TestClass<string>
{
    public string GetName()
    {
        // do work knowing that the type is a string
    }

    // other code specific to the string case
}
Joren