运算符和转换之间的区别(涉及泛型)

时间:2011-01-31 14:20:13

标签: c# generics casting

最近我遇到了与投射有关的奇怪问题。我所看到的每一个讨论/帖子都倾向于围绕使用强制转换,当确定要渲染的对象加上一些细节时。然而,我没有找到下面代码背后的原因:

class Program
{
    static void Main(string[] args)
    {
        var h = new SomeCommandHandler();
        var c = h as ICommandHandler<ICommand>; //this works as expected
        //var c = (ICommandHandler<ICommand>)h; //this throws - why?
    }

    interface ICommand { }
    class SomeCommand : ICommand { }

    interface ICommandHandler<I> where I : ICommand { }
    class SomeCommandHandler : ICommandHandler<SomeCommand> { }
}

那么为什么第二个调用抛出异常?我不知道铸造和操作员之间的区别是什么?

编辑: 它会在上面的注释行中抛出 “Unhandled Exception:System.InvalidCastException:无法将类型为'SomeCommandHandler'的对象强制转换为'ICommandHandler`1 [ConsoleApplication1.Program + ICommand]'”

5 个答案:

答案 0 :(得分:9)

嗯,这就是那里的整个差异。如果对象无法转换为该类型,as运算符将返回null,并且只是转换会产生异常。

答案 1 :(得分:2)

其他人已经解释了直接投掷抛出异常和as在投射失败时返回null之间的区别。为了能够使这样的演员成功,你需要使通用接口逆变:

interface ICommandHandler<out I> where I : ICommand { }

然而,这可能是不可能的,这取决于界面的真实外观(我假设你为了简洁而展示了一个精简的版本)。如果你的接口包含接受I类型的参数的方法,那么这将不起作用;类型I必须仅出现在get-operations中:

interface ICommandHandler<out I> where I : ICommand 
{
    void SetCommand(I n); // this would not be allowed...
    I GetCommand();       // ...but this would.
}

答案 2 :(得分:1)

它会抛出一个异常,因为h的类型为SomeCommandHandler ICommandHandler<SomeCommand>并且您尝试将其强制转换为ICommandHandler<ICommand>,这是另一种类型。

答案 3 :(得分:0)

演员表失败,因为ICommandHandler<SomeCommand>不是ICommandHandler<ICommand>。有关详细信息,请参阅here。实例

当实例不是指定类型时,as只返回null,而投射会抛出InvalidCastexception

答案 4 :(得分:0)

变量c是a为空。它不会抛出,因为这就是使用“as”的意思。换句话说,实例h不是ICommandHandler的实例。

下一行抛出是因为您试图强制将SomCommandHandler实例强制转换为ICommandHandler的实例

有意义吗?

相关问题