【问题标题】:What happen when you cast from an abstract to an interface?当您从抽象转换为接口时会发生什么?
【发布时间】:2016-01-24 23:57:01
【问题描述】:

谁能解释一下当您从抽象/界面转换到界面时,幕后究竟发生了什么?
示例:假设AbstractClasse a = new Concrete()Concrete 同时实现了IText 接口和AbstractClasse,我们说IText = (IText)a

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        interface IText
        {
            string ToText();
        }
        class Subtip : SubtitleFormat, IText
        {
            public int Error { get; set; }

            public Subtip(int error)
            {
                Error = error;
            }
            public string ToText()
            {
                return $"{Error}, Hello!";
            }
        }
        abstract class SubtitleFormat
        {
            protected int _errorCount = 1;

            public int ErrorCount
            {
                get
                {
                    return _errorCount;
                }
            }
        }
        static void Main(string[] args)
        {
            SubtitleFormat sb = new Subtip(10);
            IText sb2 = sb as IText;

            Console.WriteLine(sb.ErrorCount);
            Console.WriteLine((sb as Subtip).Error);
            Console.WriteLine(sb2.ToText());
            Console.ReadLine();
        }
    }
}

【问题讨论】:

  • 对于初学者来说,as 关键字与强制转换不同,如果无法进行强制转换并且通常速度较慢,则强制转换将引发异常。要回答您的问题,尽管as 关键字生成为 isinst IL 指令,这会导致 VM 调用遍历类类型的继承列表的例程以及 VM 创建的包含类实现的所有接口的单独数组。

标签: c# interface polymorphism abstract


【解决方案1】:

当您转换为接口或类时,相关对象的正确类型用于确定它是否与目标兼容。对象当前键入的内容在很大程度上无关紧要 - objectinterface、最终 class 或基础 class

因此,例如,您可以这样做:

SubtitleFormat sb = new Subtip(10);
IText sb2 = sb as IText;
Subtip sb3 = sb2 as Subtip;

这两个转换都是有效的,所以在它的末尾sb3 将有一个非空值。所有三个变量(sbsb2sb3)都将引用同一个对象,因此 Object.ReferenceEquals(sb, sb3) 将为真。

因为使用对象实例的真实类型来确定强制转换是否会起作用,所以像这样不会起作用:

public class NotIText : SubtitleFormat
{
    public string ToText()
    {
        return "";
    }
}

static void Main(string[] args)
{
    SubtitleFormat sb = new NotIText();
    IText sb2 = sb as IText;
}

【讨论】:

    【解决方案2】:

    只需在编译时将引用视为另一种类型,即可将类类型的值转换为对象类型或由该类实现的接口类型。同样,对象类型的值或接口类型的值可以在不更改引用的情况下转换回类类型(但在这种情况下当然需要运行时类型检查)。

    来源CSharp 语言规范

    【讨论】:

      猜你喜欢
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 2018-05-16
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多