如何为泛型提供默认类型?

时间:2009-07-08 17:24:36

标签: c# .net generics .net-2.0

我有一个类,当前有几个采用整数参数的方法。这些整数映射到应用程序可以执行的操作。我想使类通用,以便类的使用者可以提供它们具有的所有操作的枚举类型,然后方法将采用该枚举类型的参数。但是,我希望它们能够根本不指定泛型类型,并将其默认返回到整数,而不改变当前方式的语法。这可能吗?

6 个答案:

答案 0 :(得分:58)

那么......为什么不使用简单的继承呢?像:

class MyGenericClass<T>
{
}

class MyGenericClass : MyGenericClass<int>
{
}

这样你可以写两种方式:

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

答案 1 :(得分:3)

保留原始版本(非通用版本)并创建它的通用版本。

然后从非通用版本调用通用版本。

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);
}

答案 2 :(得分:3)

你不能在类的定义中这样做:

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

如果确实将默认类型的隐含性视为int,则必须使用静态工厂方法,尽管我没有看到它的值。

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

请参阅下文,了解您如何从中获益。

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

如果你想更进一步,你可以创建一个静态工厂类来解决这个问题,但如果你这样做是因为除了提供默认类型之外没有其他原因,这是一个更加荒谬的解决方案:

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>();

答案 3 :(得分:1)

编译器可以根据传递的参数类型在大多数时间推断方法的类型参数:

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

可以用

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

顺便说一句,你也可以使用泛型方法的非泛型重载。

答案 4 :(得分:0)

我确定您已经摆脱了这一点,但是我正在研究类似的问题,并且发现这种解决方案使用的是我不熟悉的“使用”上下文。他们需要将其放在自己的命名空间中,因此它并不完全完美。

namespace mygeneric
{
    public class SecurityContext<T>
    {

    }
}

namespace mytest
{
    using SecurityContext = mygeneric.SecurityContext<int>;
    using mygeneric;

    enum MyContexts
    {
        User,
        Admin
    }
    class MyTest
    {
        SecurityContext myDefaultContext;
        SecurityContext<MyContexts> mySpecialContext;
    }
}

答案 5 :(得分:0)

大多数情况下,编译器可以根据传递的参数类型推断字段的类型参数:

import lombok.Data;

@Data
public class MyClass<T> {

    private T myField;
}

可以用作,

MyClass myClass = new MyClass();
String abc = "hello world !";
myClass.setMyField(abc);
System.out.println("test generic class with generic field = " + myGenericClass.getMyField());

这应该导致,

test generic class with generic field = hello world !