以下代码是我正在编写的程序的一个简单示例。
public class Y
{ }
public class X : Y
{ }
public class W : Y
{ }
public interface IAaa<T>
where T : Y
{
void Execute(T ppp);
}
public abstract class Aaa<T> : IAaa<T>
where T : Y
{
public abstract void Execute(T ppp);
}
public class Bbb : Aaa<X>
{
public override void Execute(X ppp)
{ }
}
public class Ccc : Aaa<W>
{
public override void Execute(W ppp)
{ }
}
public class Factory
{
public static IAaa<Y> Get(bool b)
{
if(b)
return new Bbb();
else
return new Ccc();
}
}
class Program
{
static void Main(string[] args)
{
IAaa<Y> aa;
aa = Factory.Get(true);
}
}
当我编译它时,我得到以下错误
错误CS0266:无法隐式转换类型'ConsoleApplication3.Bbb' 到'ConsoleApplication3.IAaa'。一个明确的 存在转换(你错过了演员吗?)
错误CS0266:无法隐式转换类型'ConsoleApplication3.Ccc' 到'ConsoleApplication3.IAaa'。一个明确的 存在转换(你错过了演员吗?)
有没有办法让它发挥作用?
答案 0 :(得分:1)
您无法以您尝试的方式使用该界面。查找covariance/contravariance,您尝试与可能的相反(您在界面中可能<in T>
,但您尝试使用<out T>
)。
以课程Bbb
为例 - 它有一个Execute(X)
方法。如果您尝试传递Y
(可能是X
可能不是IAaa
),会发生什么?编译器不允许它,因为你从未在代码中定义在这种情况下会发生什么。
您可以通过创建和实施另一个界面public interface IAaa
{
void Execute(Y ppp);
}
来执行您想要的操作。 E.g。
void Main()
{
IAaa aa;
aa = Factory.Get(true);
}
public class Y
{ }
public class X : Y
{ }
public class W : Y
{ }
public interface IAaa<T> : IAaa
where T : Y
{
void Execute(T ppp);
}
public interface IAaa
{
void Execute(Y ppp);
}
public abstract class Aaa<T> : IAaa<T>
where T : Y
{
public abstract void Execute(T ppp);
void IAaa.Execute(Y ppp)
{
this.Execute(ppp);
}
protected abstract void Execute(Y ppp);
}
public class Bbb : Aaa<X>
{
public override void Execute(X ppp)
{ }
protected override void Execute(Y ppp)
{
this.Execute((X)ppp);
}
}
public class Ccc : Aaa<W>
{
public override void Execute(W ppp)
{ }
protected override void Execute(Y ppp)
{
this.Execute((W)ppp);
}
}
public class Factory
{
public static IAaa Get(bool b)
{
if(b)
return new Bbb();
else
return new Ccc();
}
}
也许是这样实现的,所以如果你尝试用无效的类型调用它,就会抛出一个强制转换异常:
{{1}}
答案 1 :(得分:0)
正如错误所说,你错过了演员。我相信这就是你所需要的:
public static IAaa<Y> Get(bool b)
{
if(b)
return (IAaa<Y>)(new Bbb());
else
return (IAaa<Y>)(new Ccc());
}
答案 2 :(得分:0)
您可以转换为(IAaa<Y>
)并且您的代码将被编译。
但是它不起作用,并且在运行时会失败。
为什么?
您的类Bbb
和Ccc
是专用类,Execute方法无法处理所有类型的Aaa
。你必须告诉C#/编译器。
<强>更新强>
通过拥有通用工厂,您可以获得IAaa的专用实例,并且您的代码应该可以工作。
在Program
中,当您向工厂传递TRUE或FALSE时,您已经知道了类型,因此您需要明确告诉C#您要使用的接口实现的类型。
(相应地重构Factory类,我只是发送应编译的内容)
public class Y
{ }
public class X : Y
{ }
public class W : Y
{ }
public interface IAaa<T>
where T : Y
{
void Execute(T ppp);
}
public abstract class Aaa<T> : IAaa<T>
where T : Y
{
public abstract void Execute(T ppp);
}
public class Bbb : Aaa<X>
{
public override void Execute(X ppp)
{ }
}
public class Ccc : Aaa<W>
{
public override void Execute(W ppp)
{ }
}
public class Factory<T> where T : Y
{
public static IAaa<T> Get(bool b)
{
if(b)
return (IAaa<T>)new Bbb();
else
return (IAaa<T>)new Ccc();
}
}
class Program
{
static void Main(string[] args)
{
IAaa<X> aa;
aa = Factory<X>.Get(true);
}
}
更新2
只是一个如何重构Factory类的例子:
public class Factory<T, U>
where T : Y
where U : Aaa<T>, new()
{
public static IAaa<T> Get()
{
return (IAaa<T>)new U();
}
}
class Program
{
static void Main(string[] args)
{
IAaa<X> aa;
aa = Factory<X, Bbb>.Get();
}
}