用于泛型继承的 C# 工厂
C# Factory for generic inheritance
对于这个相当基本的问题,我深表歉意,但是,我找不到任何文档。也许是因为我不知道正确的术语。
Class结构:
class D{}
abstract class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
我试图创建一个工厂方法 returning C,而总体 return 类型必须是 A。不幸的是,这种实现会产生编译时错误,尽管继承结构似乎是完美的协变。
public A<T> FactoryMethod()
{
return new 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():
}
更新
我必须按如下方式创建三个对象。
A<string> first = FactoryMethod(1, string);
A<int> second = FactoryMethod(2, int);
A<int> third = FactoryMethod(3, int);
在包含FactoryMethod
的class范围内,T
是没有意义的。您需要指定 A
的泛型参数才能将其用作类型。
在这种情况下,因为 C
是 B<D>
,而 B<D>
是 A<D>
,那么您将使用 A<D>
作为 return类型。
关于你的第二个问题,如果你将工厂方法设为泛型,我想你可以得到你想要的。
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);
}
}
因为 C
(A<D>
) 不可分配给某些 A<T>
(编译器不知道当 T
是 D
) 这不是类型安全的。
C
是绑定类型 A<D>
的子 class。所以以下是有效的:
public A<D> FactoryMethod()
{
return new C();
}
因为我们可以安全地说 C
是 A<D>
。但是 C
不是通用类型,不能转换为开放类型 A<T>
,其中 T 是通用参数,因为 T
可以是任何类型。
但是以下内容有效:
public A<T> FactoryMethod()
{
return new B<T>();
}
因为 B<T>
也是一个开放泛型类型,任何 B<T>
都是 A<T>
。
根据您的更新,您可以将工厂方法编写为:
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
}
情况 3 的那个奇怪的 hack 有点难看。那么你可以称它为:
A<string> first = FactoryMethod<string>(1);
A<int> second = FactoryMethod<int>(2);
A<int> third = FactoryMethod<int>(3); // InvalidCastException!
鉴于此:
class D{}
class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
enum openT
{
level1, level2
}
我认为您可能正在寻找这个:
public A<T> FactoryMethod<T>(openT i)
{
if(i == openT.level1)
return new A<T>():
if(i == openT.level2)
return new B<T>():
}
public A<D> FactoryMethod()
{
return new C():
}
public static void Main()
{
A<string> first = OpenFactoryMethod<string>(1);
A<int> second = OpenFactoryMethod<int>(2);
A<D> third = FactoryMethod();
}
请注意,A 不能是抽象的,因为您正在尝试构造它。
虽然我没看到你在这里真正想要完成什么,因为 C 是一个封闭类型,因此你的工厂方法对它来说永远没有意义。
已更新
以下可能更接近您要查找的内容:
public TAofT FactoryMethod<TAofT, T>() where TAofT : A<T>, new()
{
return new TAofT():
}
public static void Main()
{
A<string> first = FactoryMethod<A<string>, string>();
A<int> second = FactoryMethod<B<int>, int>();
A<D> third = FactoryMethod<C, D>();
}
但是工厂方法似乎是多余的,因为你可以这样做:
public static void Main()
{
A<string> first = new A<string>();
A<int> second = new B<int>();
A<D> third = new C();
}
更新 2
除非你真正想要的是这个:
public abstract class AEnum<T, T3> where T3 : B<T>, new()
{
private static Func<A<T>> factoryMethod;
public static readonly Level1 = new AEnum<T>(()=>new A<T>());
public static readonly Level2 = new AEnum<T>(()=>new B<T>());
public static readonly Level3 = new AEnum<T>(()=>new T3());
protected AEnum(Func<A<T>> factoryMethod) { this.factoryMethod = factoryMethod; }
public A<T> New() { return this.factoryMethod(); }
}
这样使用:
public class DEnum : AEnum<D, C>
{
}
与:
public static void Main()
{
A<D> first = DEnum.Level1.New();
A<D> second = DEnum.Level2.New();
A<D> third = DEnum.Level3.New();
}
但是你不能混合枚举类型,因为上面的类型限制为 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();
}
你想做什么?
对于这个相当基本的问题,我深表歉意,但是,我找不到任何文档。也许是因为我不知道正确的术语。
Class结构:
class D{}
abstract class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
我试图创建一个工厂方法 returning C,而总体 return 类型必须是 A。不幸的是,这种实现会产生编译时错误,尽管继承结构似乎是完美的协变。
public A<T> FactoryMethod()
{
return new 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():
}
更新
我必须按如下方式创建三个对象。
A<string> first = FactoryMethod(1, string);
A<int> second = FactoryMethod(2, int);
A<int> third = FactoryMethod(3, int);
在包含FactoryMethod
的class范围内,T
是没有意义的。您需要指定 A
的泛型参数才能将其用作类型。
在这种情况下,因为 C
是 B<D>
,而 B<D>
是 A<D>
,那么您将使用 A<D>
作为 return类型。
关于你的第二个问题,如果你将工厂方法设为泛型,我想你可以得到你想要的。
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);
}
}
因为 C
(A<D>
) 不可分配给某些 A<T>
(编译器不知道当 T
是 D
) 这不是类型安全的。
C
是绑定类型 A<D>
的子 class。所以以下是有效的:
public A<D> FactoryMethod()
{
return new C();
}
因为我们可以安全地说 C
是 A<D>
。但是 C
不是通用类型,不能转换为开放类型 A<T>
,其中 T 是通用参数,因为 T
可以是任何类型。
但是以下内容有效:
public A<T> FactoryMethod()
{
return new B<T>();
}
因为 B<T>
也是一个开放泛型类型,任何 B<T>
都是 A<T>
。
根据您的更新,您可以将工厂方法编写为:
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
}
情况 3 的那个奇怪的 hack 有点难看。那么你可以称它为:
A<string> first = FactoryMethod<string>(1);
A<int> second = FactoryMethod<int>(2);
A<int> third = FactoryMethod<int>(3); // InvalidCastException!
鉴于此:
class D{}
class A<T>{}
class B<T> : A<T> {}
class C : B<D> {}
enum openT
{
level1, level2
}
我认为您可能正在寻找这个:
public A<T> FactoryMethod<T>(openT i)
{
if(i == openT.level1)
return new A<T>():
if(i == openT.level2)
return new B<T>():
}
public A<D> FactoryMethod()
{
return new C():
}
public static void Main()
{
A<string> first = OpenFactoryMethod<string>(1);
A<int> second = OpenFactoryMethod<int>(2);
A<D> third = FactoryMethod();
}
请注意,A 不能是抽象的,因为您正在尝试构造它。
虽然我没看到你在这里真正想要完成什么,因为 C 是一个封闭类型,因此你的工厂方法对它来说永远没有意义。
已更新
以下可能更接近您要查找的内容:
public TAofT FactoryMethod<TAofT, T>() where TAofT : A<T>, new()
{
return new TAofT():
}
public static void Main()
{
A<string> first = FactoryMethod<A<string>, string>();
A<int> second = FactoryMethod<B<int>, int>();
A<D> third = FactoryMethod<C, D>();
}
但是工厂方法似乎是多余的,因为你可以这样做:
public static void Main()
{
A<string> first = new A<string>();
A<int> second = new B<int>();
A<D> third = new C();
}
更新 2
除非你真正想要的是这个:
public abstract class AEnum<T, T3> where T3 : B<T>, new()
{
private static Func<A<T>> factoryMethod;
public static readonly Level1 = new AEnum<T>(()=>new A<T>());
public static readonly Level2 = new AEnum<T>(()=>new B<T>());
public static readonly Level3 = new AEnum<T>(()=>new T3());
protected AEnum(Func<A<T>> factoryMethod) { this.factoryMethod = factoryMethod; }
public A<T> New() { return this.factoryMethod(); }
}
这样使用:
public class DEnum : AEnum<D, C>
{
}
与:
public static void Main()
{
A<D> first = DEnum.Level1.New();
A<D> second = DEnum.Level2.New();
A<D> third = DEnum.Level3.New();
}
但是你不能混合枚举类型,因为上面的类型限制为 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();
}
你想做什么?