2010-10-24 34 views
4

我有以下结构:在C#创建泛型方法

public enum MyTypes 
{ 
    Type1 = 1, 
    Type2 = 2, 
    Type3 = 3 
} 

public abstract class class1 
{ 
    int id; 
    string name; 
    MyType type; 
} 

public class class2 : class1 
{ 

} 


public class class3 : class1 
{ 

} 

public class class4 : class1 
{ 

} 

现在我想要做的就是让一个通用的方法,我想给它的对象类型说,3类,它会创建从3类对象,并定义了它的变量并返回它能够将它添加到Class列表

private class1 myFunction (MyType t , int id , string name) 
{ 
    T obj = new T(); 
    obj.type = t ; 
    obj.id = id ; 
    obj.name = name; 
    return obj; 
} 

如何创建此泛型方法?

请尽快帮我,你可以

由于提前

+1

如果你想从它们实例化对象,那些派生类(class2 - class4)不能是抽象的。 – Dialecticus 2010-10-24 12:59:26

+0

...以及为什么枚举?如果你确实需要一个枚举来反映类型出于某种原因,在特定类型的构造函数中设置它(或者更好,只需将它作为一个计算属性返回)。 – SoftMemes 2010-10-24 13:08:24

+0

是的我很抱歉误输,你是对的 – 2010-10-24 13:08:34

回答

13

丹尼陈说,在他的回答,你将不得不修改你的类定义了一点,它的工作,那么你可以做类似如下:

public T myFunction<T>(int id, string name) where T : class1, new() 
{ 
    T obj = new T(); 
    obj.id = id; 
    obj.name = name; 
    return obj; 
} 

这个通用的方法需要的类型参数T来自class1并且还有一个无参数的构造函数 - 这就是where T : class1, new()的含义。

由于idname属性通过class1基类中定义,可以再设置这些到任何通入通过其参数myFunction


做更多的事情需要注意class1

  • 考虑制定class1的接口,而不是一个抽象类,因为它不包含任何功能。
  • id,name,type需要公开,如果你真的想要能够访问它们。
  • 通常,字段实际上并未公开为public。考虑使用属性来代替这个目的。
2

不,这是不可能的,因为所有这些类abstract(不能被实例化)。我们不能创建一个抽象类的实例。

+0

不,这是我的错误,我已经修复它,只有父类是抽象的,其他类从它继承 – 2010-10-24 13:11:35

+0

我认为你的意思是“不能实例化”而不是“继承自”。 – 2010-10-24 13:27:58

0

如果我理解正确,请问如何创建Factory pattern。这正是此模式的设计目的:指定所需对象的类型并将其返回给您。

或者,您可以在函数中使用类型的开关。

private class1 myFunction (MyType t , int id , string name) 
{ 
    class1 obj; 
    switch(t) 
    { 
     case MyTypes.Type1: 
      obj = new Class1(); 
     ... 
    } 

    obj.type = t ; 
    obj.id = id ; 
    obj.name = name; 
    return obj; 
} 

第三种方法是使用泛型。

private T myFunction<T>(MyType t , int id , string name) where T : class1, new() 
{ 
    T obj = new T(); 
    obj.type = t ; 
    obj.id = id ; 
    obj.name = name; 
    return obj; 
} 

你会这样称呼它:

var obj = myFunction<Class3>(MyTypes.Type3, 5, "some name"); 
0

什么你正在寻找basicly是抽象工厂设计模式。 http://en.wikipedia.org/wiki/Abstract_factory_pattern

这样做以下

private class1 createSpecializedType<T>(MyType t, int id, string name) where T: class1, new() 
{ 
    T obj = new T(); 
    obj.type = t ; 
    obj.id = id ; 
    obj.name = name; 
    return obj; 
} 

public class1 createMyType(MyType t, int id, string name) 
{ 
    switch(t) 
    { 
     case Type1: 
       return this.createSpecializedType<class2>(t, id, name); 
     case Type2: 
       return this.createSpecializedType<class3>(t, id, name); 
     case Type3: 
       return this.createSpecializedType<class4>(t, id, name); 
    } 
} 

代码没有测试,应该被认为是伪代码。

这将允许您调用createMyType,它会根据参数计算出您想要的类,并返回正确的对象。

PS:当然,这些类是抽象的,不能实例化。但我怀疑这是复制/重写代码时引入的错误。

+1

我相信你在'T'上缺少'new()'类型约束。 – stakx 2010-10-24 13:12:31

+0

正确,谢谢。添加它。 – 2010-10-24 13:14:16

0

如果我理解正确,MyTypes和类的实际类型表达相同的东西。在这种情况下,你需要有某种映射从MyTypes实际类,例如:

static Dictionary<MyTypes, Type> typeMapping = new Dictionary<MyTypes, Type> 
    { 
    { MyTypes.Type1, typeof(class2) }, 
    { MyTypes.Type2, typeof(class3) }, 
    { MyTypes.Type2, typeof(class4) }, 
    }; 

然后,你可以使用反射来创建指定类型的实例:

private class1 myFunction(MyType t, int id, string name) 
{ 
    class1 obj = (class1)typeMapping[t].GetConstructor(Type.EmptyTypes).Invoke(null); 
    obj.type = t ; 
    obj.id = id ; 
    obj.name = name; 
    return obj; 
} 
+0

如果在编译时已知所有类型,交换机会更好。如果您确实需要在运行时操作映射,则还可以从枚举中将字典设置为Action 以避免反射。最后,如果你确实需要反思,Activator.CreateInstance更好。 =) – SoftMemes 2010-10-24 13:16:37