C# Cast有时抛出异常,但是;作为「;然后是解引用,则不需要

C# Cast有时抛出异常,但是;作为「;然后是解引用,则不需要,c#,C#,我希望这适合这个网站,因为我已经找到了答案,所以这更多的是一个测验而不是一个问题 此C#代码工作正常: WidgetRef = widget as IWidget; WidgetRef.Init(); 但是,如果我尝试将其更改为: WidgetRef = (IWidget)widget; WidgetRef.Init(); 在某些情况下,我会遇到“无法强制转换到IWidget”异常 起初,我不明白这是怎么可能的,因为如果它不能在第二个示例中强制转换,那么它应该在第一个示例中抛出一个null异

我希望这适合这个网站,因为我已经找到了答案,所以这更多的是一个测验而不是一个问题

此C#代码工作正常:

WidgetRef = widget as IWidget;
WidgetRef.Init();
但是,如果我尝试将其更改为:

WidgetRef = (IWidget)widget;
WidgetRef.Init();
在某些情况下,我会遇到“无法强制转换到IWidget”异常

起初,我不明白这是怎么可能的,因为如果它不能在第二个示例中强制转换,那么它应该在第一个示例中抛出一个null异常。但我发现不一定如此:)


这是怎么可能的?

as运算符如果无法执行强制转换,将返回null


as
operator on

如果未能执行强制转换,
as
运算符将返回null


as

上的操作符as关键字的行为与强制转换关键字相同,只是当强制转换失败时,它会将对象设置为null而不是引发异常。

as关键字的行为与强制转换关键字相同,只是在强制转换失败时,它会将对象设置为null而不是引发异常失败。

我猜您的代码的其余部分发生了一些事情,使小部件对象无法“铸造”。演员和“As”不是一回事。也许这篇文章可以给你一些想法


我猜在您的代码的其余部分发生了一些事情,使得小部件对象不是“可铸造的”。演员和“As”不是一回事。也许这篇文章可以给你一些想法


它们产生不同的IL,所以这完全不是一回事。我想这一切都取决于您如何定义IWidget和WidgetRef。我不能确切地告诉你是什么导致了这种行为

也许Init是一个静态方法,所以它可以在示例1中运行,因为“as”不会抛出异常


由于您说的是“在某些情况下”,它会引发异常,因此问题不在于.Init(),而在于强制转换。

它们生成不同的IL,因此这完全不是同一件事。我想这一切都取决于您如何定义IWidget和WidgetRef。我不能确切地告诉你是什么导致了这种行为

也许Init是一个静态方法,所以它可以在示例1中运行,因为“as”不会抛出异常


由于您说的是“在某些情况下”,它会抛出一个异常,因此问题不在于.Init(),而在于强制转换。

好的,下面是答案

我所做的错误假设是,
WidgetRef
是一个变量或字段。它实际上是一个属性,定义如下:

    private IWidget _widgetRef;
    private IWidget WidgetRef
    {
        get { return _widgetRef ?? new NullWidget(); }
        set { _widgetRef = value; }
    }

其中
NullWidget
是一个以最小方式实现
IWidget
的类。因此,即使
null
被分配到
WidgetRef
,那也不是它的结果

好的,这是答案

我所做的错误假设是,
WidgetRef
是一个变量或字段。它实际上是一个属性,定义如下:

    private IWidget _widgetRef;
    private IWidget WidgetRef
    {
        get { return _widgetRef ?? new NullWidget(); }
        set { _widgetRef = value; }
    }

其中
NullWidget
是一个以最小方式实现
IWidget
的类。因此,即使
null
被分配到
WidgetRef
,那也不是它的结果

Init()
作为扩展方法的可能重复是一种可能性。我认为另一个问题不是dup。您需要提供关于Widget类和IWidget接口的更多信息,例如它们是如何实现的?请记住,as关键字“as运算符不能执行其他转换,例如用户定义的转换,而这些转换应该使用强制转换表达式来执行。”我同意dlev,否则,第一个示例在.Init()上也会失败,WidgetRef为null。@dlev,在我的情况下不是这样,我真的怀疑这是否会奏效。。。编译器总是试图调用IWidget.Init(),而不是扩展方法可能重复的
Init()
作为扩展方法是一种可能性。我认为另一个问题不是dup。您需要提供关于Widget类和IWidget接口的更多信息,例如它们是如何实现的?请记住,as关键字“as运算符不能执行其他转换,例如用户定义的转换,而这些转换应该使用强制转换表达式来执行。”我同意dlev,否则,第一个示例在.Init()上也会失败,WidgetRef为null。@dlev,在我的情况下不是这样,我真的怀疑这是否会奏效。。。编译器将始终尝试调用IWidget.Init(),而不是扩展方法本文不适用于我的情况,即我正在转换到接口的情况本文不适用于我正在转换到接口的情况