为什么接口“切片”的类的GetType()告诉我它的类类型不是?

问题描述 投票:0回答:3

Here's我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            ISampleInterface a = new A();
            ISampleInterface b = new B();

            a.SampleMethod();
            b.SampleMethod();

            //Console.WriteLine(a.myValue); // can't do it!! a is not A
            Console.WriteLine(a.GetType()); // uhm...
        }
    }

    interface ISampleInterface
    {
        void SampleMethod();
    }

    class A : ISampleInterface
    {
        public double myValue = 10.0;

        public void SampleMethod() {
            Console.WriteLine("A");
        }
    }

    class B : ISampleInterface
    {
        public double myValue = 20.0;

        public void SampleMethod() {
            Console.WriteLine("B");
        }
    }
}

我通过接口初始化一个类(由类实现)。

显然,无法访问a.myValue,因为正确的Rextester.ISampleInterface不包含这样的定义。

但是如果我问编译器哪个类型是a,它会输出Rextester.A(我相信不是这样)。

为什么?更重要的是,哪种类是a?一种受其界面限制的混合切片类?不确定我将如何定义它...

c# class types interface
3个回答
2
投票

您可以调用哪些方法(在reflection / dynamic之外)基于变量的编译时类型。

引用转换(它是对它实现的接口的现有引用的内容)不会改变对象的类型。但是,如果您将该转换的结果存储在变量中,则变量的类型才是最重要的。

在.NET世界中,没有什么能比得上C ++的切片(我认为你所指的是切片),我能想到 - 当然你不会从编写简单的代码中得到它。

声明为接口类型的变量永远不会包含对“仅”接口的引用。它将始终是某个特定具体结构/类类型的对象。


1
投票

但是,如果我问编译器哪个类型是a,它输出Rextester.A(我不相信)

如果通过“询问编译器”你的意思是调用a.GetType(),那不是你正在做的事情。您要求运行时获取a引用的对象的实际类型。运行时正确地告诉你它是一个Rextester.A

另一方面,编译器不知道这一点。该变量被声明为ISampleInterface,因此所有编译器都可以安全地执行绑定到接口定义的方法。

如果将变量强制转换为A,则可以访问其成员:

A newA = a;
newA.myValue = 15;  // perfectly valid

请注意,a引用的实际对象没有改变(意味着它是同一个对象 - 显然你改变了它的一个成员字段)。您仍然可以通过a或类通过newA引用作为接口。

如果您曾向编译器询问a的类型,但使用如下方法:

public Type GetCompileTimeType<T>(T inputObject)
{
    return typeof(T);
}

(信用卡qsxswpoi)

并打电话

this answer

你会得到Console.WriteLine(GetCompileTimeType(a));


0
投票

Rextester.ISampleInterface无法访问,因为它的范围为a.myValue

ISampleInterface正确地导致a.GetType(),因为这在运行时被解析为分配给A的类型的实例,即a。它仅在A的范围内。

例如...

ISampleInterface

您正在创建一个声明为ISampleInterface a = new A(); A实例。

ISampleInterface

您可以访问声明的内容。

a.SampleMethod();

您无法访问未声明的内容。

Console.WriteLine(a.myValue);

Console.WriteLine(a.GetType()); 可以从GetType调用,它可以自然地扩展,所以你可以调用它,因为它是从一个隐式基类型声明的。在这种情况下,System.Object返回GetType,因为这正是A的意思; a的一个例子。

© www.soinside.com 2019 - 2024. All rights reserved.