“重新构建”一个子类实例(声明为基类)到接口 - 它为什么有效?

时间:2017-01-26 13:11:37

标签: c# type-conversion

我希望有子类实现任意接口,但是被声明为基类,因此应用程序会尝试将实例“重新”重新设置到该接口,并在重铸成功时使用它们。

我有些怀疑,所以我做了这个短的尖峰,无论是为了我的喜悦和惊喜,它都有效。

我的问题是:为什么以及如何运作?有没有一种正式的方式,我可以知道它会预先工作? C#中的某种“投射规则”?

class Program
{
    static void Main(string[] args)
    {
        var obj = new SubClass() as BaseClass;

        Console.WriteLine(obj is ISubClass); // output = "True"

        Console.ReadKey();
    }
}

class BaseClass { }

class SubClass : BaseClass, ISubClass { }

interface ISubClass { }

5 个答案:

答案 0 :(得分:2)

该对象仍属于SubClass类型,您只能将BaseClass的类型用作参考。因为它是SubClass类型,它也会实现ISubClass接口。强制转换不会更新原始对象,它只会“更改对象的引用”。

就像您在代码中显示的那样,只需进行简单的更改:

  1. 您创建了一个SubClass对象:SubClass obj = new SubClass();
  2. 现在你施放它:BaseClass bObj = obj as BaseClass;但原始对象仍然是SubClass类型。您也可以执行此操作ISubClass sObj = obj as ISubClass;ISubClass sObj = bObj as ISubClass,因为您始终使用原始对象。
  3. 另一个例子是多态性。当铸造时改变原始物体时,整个概念将不起作用。

    • 作为一般提示,您不需要对var obj = new SubClass() as BaseClass;进行明确表达,这也可以:BaseClass obj = new SubClass();

答案 1 :(得分:2)

您已创建SubClass的实例,SubClass继承自接口和BaseClass,因此我们可以将对象SubClass的引用转换为那些。实际类型仍为SubClass,您刚刚将引用转换为其基本类型,如果您通过调用实例上的GetType()进行检查,则会看到它将评估为SubClass,所以它只是引用转换,原始对象仍然是相同的。

您可能希望了解polymorphsimReference Conversion

(由OP编辑)从第二个链接:

  

如果要转换的值是空引用或引用类型本身或更多派生类型的引用类型,则从基类型到派生类型的转换仅在运行时成功。

     

(...)类类型总是可以强制转换为它实现的接口类型。类似地,从接口类型到实现它的类类型的转换仅在运行时成功,如果被转换的值是空引用或引用类型,它是类类型本身或从类类型派生的类型。

答案 2 :(得分:1)

在编译时,您无法调用SubClass的方法(即使方法是在ISublass中声明的),但在运行时,如果进行该检查,它将返回true。

答案 3 :(得分:1)

当您转换为父类时,您仅限于使用从父类继承的任何对象可用的那些方法和属性。该对象仍然是您使用new语句SubClass创建的类型。

class BaseClass
{
    public int BaseProp { get; set; }
}

class SubClass : BaseClass, ISubClass
{
    public int ChildProp { get; set; }
}

interface ISubClass
{
    int ChildProp { get; set; }
}

class Program
{
    public static void Main(string[] args)
    {
        var obj = new SubClass() as BaseClass;

        // obj IS SubClass type, but we are only going to use properties and methods
        // available to ANY BaseClass

        obj.BaseProp = 1;  // this is fine
        obj.ChildProp = 2;  // this doesn't work (BaseClass does not contain a definition for ChildProp)

        (obj as SubClass).ChildProp = 2;  // this works
    }
}

答案 4 :(得分:0)

当您使用“as”关键字时,它不会创建BaseClass的新实例。该实例仍然是SubClass。

如果您从SubClass实例创建了一个新的BaseClass实例,它将按预期显示为false。