2

以下代码是我正在编写的程序的一个简单示例。

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”。存在显式转换(您是否缺少演员表?)

有什么办法让它工作吗?

4

3 回答 3

1

您不能以您尝试的方式使用该界面。Lookup covariance/contravariance,您正在尝试做与可能相反的事情(您在界面中可能有,<in T>但您正试图像这样使用它<out T>)。

以类Bbb为例——它有一个Execute(X)方法。如果您尝试将 a Y(可能是也可能不是 a X)传递给它会发生什么?编译器不允许这样做,因为您从未在代码中定义在这种情况下应该发生什么。

你可以通过创建和实现另一个接口来做你想做的事,IAaa. 例如

public interface IAaa
{
    void Execute(Y ppp);
}

也许是这样实现的,因此如果您尝试使用无效类型调用它,则会引发强制转换异常:

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();
    }
}
于 2013-04-11T11:58:05.367 回答
0

正如错误所说,您缺少演员表。我相信这是你需要的:

public static IAaa<Y> Get(bool b)
{
    if(b)
        return (IAaa<Y>)(new Bbb());
    else
        return (IAaa<Y>)(new Ccc());
}
于 2013-04-11T11:40:13.283 回答
0

您可以转换为 ( IAaa<Y>) 并且您的代码将编译。但是它不会工作并且会在运行时失败。为什么?您的类BbbCcc是专门的类,并且 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();
    }
}
于 2013-04-11T11:54:04.050 回答