Csharp/C#教程:接口变量是否具有值类型或引用类型语义?分享


接口变量是否具有值类型或引用类型语义?

接口变量是否具有值类型或引用类型语义?

接口按类型实现,这些类型是值类型或引用类型。 显然, intstring实现IComparableint是值类型, string是引用类型。 但是这个怎么样:

 IComparable x = 42; IComparable y = "Hello, World!"; 

(我试图回答的问题可能被删除了,因为它询问接口是存储在堆栈还是堆上,而且,正如我们都应该知道的那样,考虑到它们之间的值和引用类型之间的差异更具建设性。语义而不是它们的实现。有关讨论,请参阅Eric Lippert的堆栈是一个实现细节 。)

通常,根据现有的答案,它是一个参考类型,需要拳击; 虽然有一个例外(总是不存在吗?)。 在具有where约束的generics方法where ,它可以是:

 void Foo(T obj) where T : ISomeInterface { obj.SomeMethod(); } 

这是一个受约束的操作, 即使它是值类型也不会装箱。 这是通过constrained来实现的。 相反,JIT将执行操作作为引用类型的虚拟调用,并对值类型执行静态调用。 没有拳击。

这是关于理解类型的装箱和拆箱。 在您的示例中,int在赋值时被加框,并且对该“box”或对象的引用是分配给x的内容。 值类型int被定义为实现IComparable的结构。 但是,一旦使用该接口引用引用值类型int,它将被装箱并放置在堆上。 这就是它在实践中的运作方式。 使用接口引用导致装箱按定义发生的事实使得此引用类型语义。

MSDN:拳击和拆箱

类型为IComparable变量或字段是引用类型变量或字段,与分配给该字段的值的类型无关。 这意味着示例代码中的x被加框。

一个简单的测试将certificate这一点。 该测试基于以下事实: 您只能将值类型拆分为其原始类型(以及该类型的可空版本) :

  [TestMethod, ExpectedException(typeof(InvalidCastException))] public void BoxingTest() { IComparable i = 42; byte b = (byte)i; //exception: not allowed to unbox an int to any type other than int Assert.AreEqual(42, b); Assert.Fail(); } 

编辑

最重要的是,C#规范明确地将引用类型定义为包括类类型,接口类型,数组类型和委托类型。

编辑2

正如Marc Gravell在他的回答中指出的那样,具有接口约束的generics类型是不同的情况。 这不会引起拳击。

接口类型的变量将始终具有不可变语义,可变引用语义或“古怪”语义(除了普通引用或值语义之外的其他语义)。 如果variable1variable2都被声明为相同的接口类型,则执行variable2 = variable1 ,并且一个不再写入任一变量, variable1 1引用的实例将始终与被称为variable2的实例无法区分(因为它将是同一个例子)。

具有接口约束的generics类型可能具有不可变语义,可变引用语义或“古怪”语义,但也可能具有可变值语义。 如果未将接口记录为具有可变值语义,则这可能很危险。 不幸的是,没有办法限制接口具有不可变语义或可变值语义(意味着在variable2 = variable1 ,不应该通过编写variable2来改变variable2 ,反之亦然)。 可以添加“struct”约束以及接口约束,但这将排除具有不可变语义的类,而不排除具有引用语义的结构。

上述就是C#学习教程:接口变量是否具有值类型或引用类型语义?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/950928.html

(0)
上一篇 2021年11月18日
下一篇 2021年11月18日

精彩推荐