我一直在更深入地研究反射和RTTI等概念。例如,最近我了解了dynamic_cast在C ++中如何工作。这帮助我了解了为什么将其视为运行缓慢(通常)。我发现思考C#(和.NET)与C ++之间的区别非常有帮助。这就是我最终想到“操作员是”以及它到底在做什么的方式。它进行什么样的比较?我认为它与“类型”有关。
干杯。
答案 0 :(得分:2)
7.10.10 The is operator
The is operator is used to dynamically check if the run-time type of an object is compatible with a given type. The result of the operation E is T, where E is an expression and T is a type, is a boolean value indicating whether E can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. The operation is evaluated as follows, after type arguments have been substituted for all type parameters:
• If E is an anonymous function, a compile-time error occurs
• If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
• Otherwise, let D represent the dynamic type of E as follows:
o If the type of E is a reference type, D is the run-time type of the instance reference by E.
o If the type of E is a nullable type, D is the underlying type of that nullable type.
o If the type of E is a non-nullable value type, D is the type of E.
• The result of the operation depends on D and T as follows:
o If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
o If T is a nullable type, the result is true if D is the underlying type of T.
o If T is a non-nullable value type, the result is true if D and T are the same type.
o Otherwise, the result is false.
Note that user defined conversions, are not considered by the is operator.
关键部分可能是“ D是E引用的实例的运行时类型”:在C#中,每个引用类型都有一个Type
字段,其中包含该类型。
所有有效的隐式引用转换都在6.1.6中定义:
The implicit reference conversions are:
• From any reference-type to object and dynamic.
• From any class-type S to any class-type T, provided S is derived from T.
• From any class-type S to any interface-type T, provided S implements T.
• From any interface-type S to any interface-type T, provided S is derived from T.
• ...
还有更多,但这些是最重要的转换。
答案 1 :(得分:1)
例如,我们采用以下代码:
var obj = GetObject();
if (obj is Program)
{
Console.WriteLine("How did we end up here?");
}
else
{
Console.WriteLine("It can't be main class!");
}
GetObject()
返回new object()
,因此它不能是入口点类的实例。
编译后的重新创建的代码如下所示:
// Token: 0x0600000D RID: 13 RVA: 0x0000233B File Offset: 0x0000053B
[STAThread]
private static void Main()
{
if (Program.GetObject() is Program)
{
Console.WriteLine("How did we end up here?");
return;
}
Console.WriteLine("It can't be main class!");
}
查看生成的IL代码时,我们可以看到以下内容:
.method private hidebysig static
void Main () cil managed
{
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = (
01 00 00 00
)
// Header Size: 1 byte
// Code Size: 34 (0x22) bytes
.maxstack 8
.entrypoint
/* 0x0000053C 280C000006 */ IL_0000: call object Test.Program::GetObject()
/* 0x00000541 7503000002 */ IL_0005: isinst Test.Program
/* 0x00000546 2C0B */ IL_000A: brfalse.s IL_0017
/* 0x00000548 7208020070 */ IL_000C: ldstr "How did we end up here?"
/* 0x0000054D 283800000A */ IL_0011: call void [mscorlib]System.Console::WriteLine(string)
/* 0x00000552 2A */ IL_0016: ret
/* 0x00000553 7238020070 */ IL_0017: ldstr "It can't be main class!"
/* 0x00000558 283800000A */ IL_001C: call void [mscorlib]System.Console::WriteLine(string)
/* 0x0000055D 2A */ IL_0021: ret
} // end of method Program::Main
称为isinst
的特殊指令检查对象的类型是否等于您提供的类型。