通用继承的C#工厂

通用继承的C#工厂,c#,generics,inheritance,factory,covariant,C#,Generics,Inheritance,Factory,Covariant,我为这个相当基本的问题道歉,但是,我找不到任何文档。也许是因为我不知道正确的术语 班级结构: class D{} abstract class A<T>{} class B<T> : A<T> {} class C : B<D> {} D类{} 抽象类A{} B类:A{} C类:B{} 我试图创建一个返回C的工厂方法,而总的返回类型必须是a。不幸的是,这个实现将产生编译时错误,尽管继承结构似乎是完全协变的 public A<T>

我为这个相当基本的问题道歉,但是,我找不到任何文档。也许是因为我不知道正确的术语

班级结构:

class D{}

abstract class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
D类{}
抽象类A{}
B类:A{}
C类:B{}
我试图创建一个返回C的工厂方法,而总的返回类型必须是a。不幸的是,这个实现将产生编译时错误,尽管继承结构似乎是完全协变的

public A<T> FactoryMethod()
{
   return new C();
}
public A FactoryMethod()
{
返回新的C();
}
更具体地说,我试图实现一个工厂,能够根据输入值生成所有三个类,同时必须获得通用功能

public A<T> FactoryMethod(int i, Type K)
{
   if(i == 1)
      return new A<K>():

   if(i == 2)
      return new B<K>():

   if(i == 3)
      return new C():
}
public A FactoryMethod(inti,类型K)
{
如果(i==1)
返回新的A():
如果(i==2)
返回新的B()
如果(i==3)
返回新的C()
}
更新

我必须创建三个对象,如下所示

A<string> first = FactoryMethod(1, string);
A<int> second = FactoryMethod(2, int);
A<int> third = FactoryMethod(3, int);
A first=FactoryMethod(1,字符串);
第二个=FactoryMethod(2,int);
第三种方法=FactoryMethod(3,int);

在包含
FactoryMethod
的类的范围内,
T
是无意义的。您需要指定
A
的泛型参数才能将其用作类型

在这种情况下,因为
C
B
,而
B
A
,所以您将使用
A
作为返回类型

对于你的第二个问题,如果你让工厂方法通用,我想你可以得到你想要的

public class A<T> {}

public class B<T> : A<T> {}

public class C : B<D> {}

public class D {}

public class Test
{
    public static A<T> FactoryMethod<T>(int i)
    {
       if(i == 1)
          return new A<T>();
       if(i == 2)
          return new B<T>();
       if(i == 3)
          return (A<T>)(object)new C();
       return null;
    }

    public static void Main()
    {
        A<string> first = FactoryMethod<string>(1);
        A<int> second = FactoryMethod<int>(2);
        A<D> third = FactoryMethod<D>(3);
    }
}
公共类A{}
公共B类:A{}
公共类C:B{}
公共类D{}
公开课考试
{
公共静态A FactoryMethod(int i)
{
如果(i==1)
返回新的A();
如果(i==2)
返回新的B();
如果(i==3)
返回(A)(对象)新的C();
返回null;
}
公共静态void Main()
{
第一种方法=工厂法(1);
第二种方法=工厂法(2);
第三种方法=工厂法(3);
}
}

因为
C
A
)不可分配给某些
A
(编译器不知道当
t
D
时,您总是传递
3
),这不是类型安全的。

在包含
FactoryMethod
的类的范围内,
t
是没有意义的。您需要指定
A
的泛型参数才能将其用作类型

在这种情况下,因为
C
B
,而
B
A
,所以您将使用
A
作为返回类型

对于你的第二个问题,如果你让工厂方法通用,我想你可以得到你想要的

public class A<T> {}

public class B<T> : A<T> {}

public class C : B<D> {}

public class D {}

public class Test
{
    public static A<T> FactoryMethod<T>(int i)
    {
       if(i == 1)
          return new A<T>();
       if(i == 2)
          return new B<T>();
       if(i == 3)
          return (A<T>)(object)new C();
       return null;
    }

    public static void Main()
    {
        A<string> first = FactoryMethod<string>(1);
        A<int> second = FactoryMethod<int>(2);
        A<D> third = FactoryMethod<D>(3);
    }
}
公共类A{}
公共B类:A{}
公共类C:B{}
公共类D{}
公开课考试
{
公共静态A FactoryMethod(int i)
{
如果(i==1)
返回新的A();
如果(i==2)
返回新的B();
如果(i==3)
返回(A)(对象)新的C();
返回null;
}
公共静态void Main()
{
第一种方法=工厂法(1);
第二种方法=工厂法(2);
第三种方法=工厂法(3);
}
}

因为
C
A
)不可分配给某些
A
(编译器不知道当
t
D
时,您总是会传递
3
),这是不安全的。

C
是绑定类型
A
的子类。因此,以下是有效的:

public A<D> FactoryMethod()
{
   return new C();
}
public A<T> FactoryMethod()
{
   return new B<T>();
}
因为
B
也是一个开放的泛型类型,任何
B
都是
A


根据您的更新,您可以将factory方法编写为:

public A<T> FactoryMethod<T>(int i)
{
   if(i == 1)
      return new A<T>():
   if(i == 2)
      return new B<T>():
   if(i == 3) 
      return (A<T>)(object)new C():
      // The cast to object gets rid of compile time checking,
      // but will throw an InvalidCastExceptoin if T is not D
}
public A FactoryMethod(inti)
{
如果(i==1)
返回新的A():
如果(i==2)
返回新的B()
如果(i==3)
返回(A)(对象)新C():
//cast to对象摆脱了编译时检查,
//但如果T不是D,则将抛出InvalidCasteException
}
对于案例3来说,这有点难看。那么你可以称之为:

A<string> first = FactoryMethod<string>(1);
A<int> second = FactoryMethod<int>(2);
A<int> third = FactoryMethod<int>(3); // InvalidCastException!
A第一个=工厂方法(1);
第二种方法=工厂法(2);
第三种方法=工厂法(3);//无效的例外!

C
是绑定类型
a
的子类。因此,以下是有效的:

public A<D> FactoryMethod()
{
   return new C();
}
public A<T> FactoryMethod()
{
   return new B<T>();
}
因为
B
也是一个开放的泛型类型,任何
B
都是
A


根据您的更新,您可以将factory方法编写为:

public A<T> FactoryMethod<T>(int i)
{
   if(i == 1)
      return new A<T>():
   if(i == 2)
      return new B<T>():
   if(i == 3) 
      return (A<T>)(object)new C():
      // The cast to object gets rid of compile time checking,
      // but will throw an InvalidCastExceptoin if T is not D
}
public A FactoryMethod(inti)
{
如果(i==1)
返回新的A():
如果(i==2)
返回新的B()
如果(i==3)
返回(A)(对象)新C():
//cast to对象摆脱了编译时检查,
//但如果T不是D,则将抛出InvalidCasteException
}
对于案例3来说,这有点难看。那么你可以称之为:

A<string> first = FactoryMethod<string>(1);
A<int> second = FactoryMethod<int>(2);
A<int> third = FactoryMethod<int>(3); // InvalidCastException!
A第一个=工厂方法(1);
第二种方法=工厂法(2);
第三种方法=工厂法(3);//无效的例外!
鉴于此:

class D{}

class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
enum openT
{
    level1, level2
}
与:

publicstaticvoidmain()
{
A first=OpenAEnum.Level1.New();
第二个=OpenAEnum.Level2.New();
第三个=OpenAEnum.Level3.New();
}
您想做什么?

鉴于此:

class D{}

class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
enum openT
{
    level1, level2
}
与:

publicstaticvoidmain()
{
A first=OpenAEnum.Level1.New();
第二个=OpenAEnum.Level2.New();
第三个=OpenAEnum.Level3.New();
}

您试图做的是什么?

您会遇到什么错误?什么是
T
?T只是普通的泛型字母。然而,D是一个具体的类。编译错误说明了什么?你不能仅仅把a
t
放在那里,除非它在这个范围内意味着什么。
C
不是泛型的-它是a
B
然后是a
a
。您不能将其作为
A
返回,因为
T
可以是任何东西。@Nex:如果
T
string
,会出现什么错误?什么是
T
?T只是普通的泛型字母。然而D
public class OpenAEnum<T, T3> : AEnum<T, T3> where T3 : B<T3>
{
}

public class CInt : B<int> {}
public class Cstring : B<string> {}
public static void Main()
{
    A<string> first = OpenAEnum<string, CString>.Level1.New();
    A<int> second = OpenAEnum<int, CInt>.Level2.New();
    A<D> third = OpenAEnum<D, C>.Level3.New();
}