为什么要使用as关键字初始化对象

4

我刚刚遇到了一些我不理解的代码。它实际上是

Class c = new BaseClass() as Class;

我不理解这样做的优势,所以我创建了自己的控制台应用程序来看看它做了什么。

namespace Initialize
{
    class Program
    {
        static void Main(string[] args)
        {
            Demo demo = new Demo();
            demo.BaseProp = "";
            demo.DemoProp = "";

            BaseDemo baseDemo = new BaseDemo();
            baseDemo.BaseProp = "";

            BaseDemo baseDemo2 = new Demo();
            baseDemo2.BaseProp = "";

            BaseDemo baseDemo3 = new Demo() as BaseDemo;
            baseDemo3.BaseProp = "";

            //fails runtime
            //Demo demo2 = (Demo)baseDemo;

            Demo demo3 = (Demo)baseDemo2;
            demo3.BaseProp = "";
            demo3.DemoProp = "";

            Demo demo4 = (Demo)baseDemo3;
            demo4.BaseProp = "";
            demo4.DemoProp = "";
        }
    }

    class BaseDemo
    {
        public string BaseProp { get; set; }
    }

    class Demo : BaseDemo
    {
        public string DemoProp { get; set; }
    }
}

我只能假设它在多态方面提供了一些额外的帮助,但我无法弄清楚如何使用它或者找到任何区别:

BaseDemo baseDemo2 = new Demo();  

并且

BaseDemo baseDemo3 = new Demo() as BaseDemo;

由于我很难想出为什么要这样做...让我说一下:我们的(继承的)代码库中有很多毫无道理的东西。如果这里实际上没有意图,只是缺乏理解,我也不会感到惊讶。 - Simon Whitehead
如原文所述,“Demo d = new BaseDemo() as Demo;” 确保等同于 “Demo d = null;” ,要么你漏掉或误解了代码的某些部分,要么开发者构建了一个毫无作用的代码。 - Sergey Kalinichenko
4个回答

4

This

Class c = new BaseClass() as Class;

这是完全无用的。如果ClassBaseClass的基类,那么转换是自动的,否则转换将始终返回null

Class c = new BaseClass()

足够了...唯一的例外:
var c = new BaseClass() as Class;

现在,c 是一个指向BaseClass的引用,类型为Class。你正在强制隐式类型变量的类型(这很无用...你可以直接写 Class c = new BaseClass();

请注意,与转换运算符()不同,as关键字不会“激活”其中一个类可能实现的implicit/explicit转换操作符。

以下代码无法编译:

class BaseClass
{
    public static implicit operator Class(BaseClass b)
    {
        return new Class();
    }
}

class Class
{            
}

Class c = new BaseClass() as Class;

如同在msdn上所述:

as操作符类似于强制类型转换。但是,如果无法进行转换,则as返回null而不是引发异常。

并且

请注意,as操作符仅执行引用转换、可空转换和装箱转换。as操作符无法执行其他转换,例如用户定义的转换,这些应该使用强制类型转换表达式来执行。


实际上,它有1个要点!我认为避免接口是一个好方法...通过这样做,它确保类型是所需的类型(演示),但只允许设置基类的属性!这让我的头发麻痹了,似乎过于复杂和非常不直观!不过,感谢您的答案,现在我明白了! - Dave

1

你说得对,在你的情况下没有区别。使用as只是在陈述一个显而易见的事实,即Demo实例也是BaseDemo的实例。

as关键字在其他上下文中也很有用,特别是当您想要测试对象是否属于某种类型,然后在强制转换成功后使用它时。


0

使用 as 进行强制类型转换,如果转换失败则返回 null。这是一种安全的方式进行类型转换,并检查是否为 null,而不是抛出异常。

我很难想象你的例子何时会被使用。


1
但构造函数从不返回null,因此强制转换是多余的。 - Ahmed KRAIEM
1
很抱歉,Class c = new BaseClass() as Class; 怎么可能是 null 呢?如果我写成 Class c; 那倒是可以理解,但既然已经初始化了,我认为它应该是被初始化了(因此不会是 null)吧? - Dave
确实。我很难想出任何人会这么做的理由。 - Simon Whitehead
我进行了一次更新,虽然更准确,但让我更加困惑。 - Dave
因为强制转换失败,所以Class c = new BaseClass() as Class;null,因为BaseClass不是Class,使得表达式new BaseClass() as Class的值为null;因此c == null - Ahmed KRAIEM
显示剩余2条评论

0
BaseDemo baseDemo2 = new Demo();  
BaseDemo baseDemo3 = new Demo() as BaseDemo;

绝对没有区别,就像if (condition == true)if (condition)之间没有区别一样。

Demo 一个BaseDemo,因此在这种情况下安全转换(as)是多余的。

另一方面:

Class c = new BaseClass() as Class;

如果使用Class 继承 BaseClass,则强制转换将失败,使得c变成null


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接