我很想知道为什么会这样.请阅读下面的代码示例以及每个部分下面的注释中发出的相应IL:
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器callvirt为第一部分发出a 而call第二部分发出a ?是否有任何理由编译器会发出callvirt非虚方法的指令?如果在某些情况下编译器将callvirt为非虚拟方法发出一个,这会产生类型安全问题吗?
我的问题与此问题有些相关:显式实现的接口和通用约束.
然而,我的问题是编译器如何启用通用约束来消除对显式实现接口的值类型进行装箱的需要.
我想我的问题归结为两部分:
幕后CLR实现发生了什么,需要在访问显式实现的接口成员时将值类型装箱,并且
删除此要求的通用约束会发生什么?
一些示例代码:
internal struct TestStruct : IEquatable<TestStruct>
{
bool IEquatable<TestStruct>.Equals(TestStruct other)
{
return true;
}
}
internal class TesterClass
{
// Methods
public static bool AreEqual<T>(T arg1, T arg2) where T: IEquatable<T>
{
return arg1.Equals(arg2);
}
public static void Run()
{
TestStruct t1 = new TestStruct();
TestStruct t2 = new TestStruct();
Debug.Assert(((IEquatable<TestStruct>) t1).Equals(t2));
Debug.Assert(AreEqual<TestStruct>(t1, t2));
}
}
Run Code Online (Sandbox Code Playgroud)
由此产生的IL:
.class private sequential ansi sealed beforefieldinit TestStruct
extends [mscorlib]System.ValueType
implements [mscorlib]System.IEquatable`1<valuetype TestStruct>
{
.method …Run Code Online (Sandbox Code Playgroud) 我最近遇到了这个Stackoverflow问题:何时使用struct?
在其中,它有一个答案,说了一些有点深刻的东西:
另外,要意识到当一个struct实现一个接口 - 就像Enumerator那样 - 并且被强制转换为该实现类型时,该struct将成为一个引用类型并被移动到堆中.在Dictionary类的内部,Enumerator仍然是一个值类型.但是,只要方法调用GetEnumerator(),就会返回引用类型的IEnumerator.
这究竟是什么意思?
如果我有类似的东西
struct Foo : IFoo
{
public int Foobar;
}
class Bar
{
public IFoo Biz{get; set;} //assume this is Foo
}
...
var b=new Bar();
var f=b.Biz;
f.Foobar=123; //What would happen here
b.Biz.Foobar=567; //would this overwrite the above, or would it have no effect?
b.Biz=new Foo(); //and here!?
Run Code Online (Sandbox Code Playgroud)
究竟什么值类型结构的详细语义被视为引用类型?
当我需要显式实现接口成员时,它是私有的.
例如 :
// when explicit implementation it is always private
void IPointy.Draw( )
{
}
Run Code Online (Sandbox Code Playgroud)
为什么要实施这样的设计规则?
注意 :
当两个接口具有相同的方法时,为了避免冲突,我必须明确地实现为
class Line :IPointy
{
// Now it is private
void IPointy.Draw( )
{
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是实施的原因是私人的.