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

时间:2019-02-28 14:48:30

标签: c# class types interface

Here's我的代码:

self.__checkHoerhelferShipping

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

很显然,无法访问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是哪种类?一种受其接口限制的混合切片类?不确定如何定义...

3 个答案:

答案 0 :(得分:2)

您可以调用的方法(外部反射/ dynamic)基于变量编译时类型

引用强制转换(即强制转换对它实现的接口的现有引用)完全不更改对象的类型。但是,如果要将转换的结果存储在变量中,那么变量的类型才是重要的。

.NET世界中没有什么可以比作C ++的切片(我想您指的是切片),我想不到-肯定不会从编写简单的代码中得到。

声明为接口类型的变量将永远不会包含对“只是”该接口的内容的引用。它将始终是某些特定的具体struct / class类型的对象。

答案 1 :(得分: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);
}

(贷记this answer

并致电

Console.WriteLine(GetCompileTimeType(a));

您将获得Rextester.ISampleInterface

答案 2 :(得分:0)

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的含义; A的实例。