views:

129

answers:

4

I have a class that currently has several methods that take integer parameters. These integers map to operations that the application can perform. I'd like to make the class generic so that the consumers of the class can provide an enum type that they have with all the operations in it, then the methods will take parameters of that enum type. However, I want them to be able to not specify a generic type at all, and have it default back to integers with no change in syntax from the current way. Is this possible?

+1  A: 

The compiler can infer the type arguments on methods most of the time based on the type of the arguments passed:

public void DoSomething<T>(T test) {
}

can be called with

DoSomething(4);                   // = DoSomething<int>(4);
DoSomething(MyEnum.SomeValue);    // = DoSomething<MyEnum>(MyEnum.SomeValue);

By the way, you can have non-generic overloads of a generic method too.

Mehrdad Afshari
I'm looking for the class to be sort of "optionally generic". I don't think it's possible so I'll just have to make generic methods with non-generic overloads... I was looking for this "SecurityContext sec = new SecurityContext();" (which would create it using integers for parameters, and then "SecurityContext<MyOperations> sec = new SecurityContext<MyOperations>();" which would create it using MyOperations for parameters
Max Schmeling
+1  A: 

Keep your original version (non-generic version) and create a generic version of it.

Then call the generic version from your non-generic version.

void Main()
{
DoSomething(2);
DoSomething(EnumValue);

}

public void DoSomething(int test) {
DoSomething<int>(test);
}

// Define other methods and classes here
public void DoSomething<T>(T test) {
Console.WriteLine(test);
}
J.W.
The generic parameter type will be the same for all methods, so I would like it at the class level. I know I could make a generic version and then inherit from it for the int version, but I was just hoping to get it all in one... but I didn't know of any way to do that. I guess it's not possible in as simple a way as I was hoping.
Max Schmeling
+1  A: 

You can't do it in the definition of the class:

var foo = new MyGenericClass(); // defaults to integer... this doesn't work
var bar = new MyGenericClass<MyEnum>(); // T is a MyEnum

If really value the implicitness of the default type being int, you'll have to do it with a static factory method, although I don't see the value of it.

public class MyGenericClass<T>
{
    public static MyGenericClass<T> Create()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> CreateDefault()
    {
        return new MyGenericClass<int>();
    }
}

See below for how you really don't benefit from the above.

var foo = MyGenericClass<MyEnum>.Create();
var bar1 = MyGenericClass.CreateDefault(); // doesn't work
var bar2 = MyGenericClass<int>.CreateDefault(); // works, but what's the point

If you want to take it even farther, you can create a static factory class that will solve this, but that's an even more ridiculous solution if you're doing it for no other reason than to provide a default type:

public static class MyGenericClassFactory
{
    public static MyGenericClass<T> Create<T>()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> Create()
    {
        return new MyGenericClass<int>();
    }
}

var foo = MyGenericClassFactory.Create(); // now we have an int definition
var bar = MyGenericClassFactory.Create<MyEnum>();
Michael Meadows
yeah, I don't want to introduce that complexity. the default isn't extremely important, it just would have been nice. i didn't know of any way to do it, but I wanted to check with all you guys first to make sure. thanks for the answer
Max Schmeling
+1  A: 

So... why not use simple inheritance? Like:

class MyGenericClass<T>
{
}

class MyGenericClass : MyGenericClass<int>
{
}

This way you can write both ways:

var X = new MyGenericClass<string>();
var Y = new MyGenericClass(); // Is now MyGenericClass<int>
Vilx-