小编Dud*_*eti的帖子

在新的c#6"的情况下调用而不是callvirt?" 空检查

鉴于这两种方法:

    static void M1(Person p)
    {
        if (p != null)
        {
            var p1 = p.Name;
        }
    }

    static void M2(Person p)
    {
        var p1 = p?.Name;
    }
Run Code Online (Sandbox Code Playgroud)

为什么M1 IL代码使用callvirt:

IL_0007:  brfalse.s  IL_0012
IL_0009:  nop
IL_000a:  ldarg.0
IL_000b:  callvirt   instance string ConsoleApplication4.Person::get_Name()
Run Code Online (Sandbox Code Playgroud)

和M2 IL使用call:

brtrue.s   IL_0007
IL_0004:  ldnull
IL_0005:  br.s       IL_000d
IL_0007:  ldarg.0
IL_0008:  call       instance string ConsoleApplication4.Person::get_Name()
Run Code Online (Sandbox Code Playgroud)

我只能猜到它,因为在M2我们知道它p不是空的,它就像它

new MyClass().MyMethod();
Run Code Online (Sandbox Code Playgroud)

这是真的吗?

如果是,如果p在其他线程中将为null?

c# clr il roslyn c#-6.0

12
推荐指数
2
解决办法
588
查看次数

成员在另一个模块中声明,需要导入

我使用Mono.Cecil创建一个新的自定义属性类型,然后将其添加到现有类型.

为了演示它,我有一个名为"Sample"的预先存在的DLL,其类型称为"SampleType".

我想使用Mono.Cecil在名为"NewAttribute"的"Sample"中编写一个新类型,然后将此属性添加到"SampleType".

代码看起来像这样:(不完全,但它足够好,例如)

static void AddCustomeAttribute()
{
    var module = ModuleDefinition.ReadModule(AssemblyName);
    var attrType = NewAttributeProvider.Add(module);
    var ctor = attrType.GetConstructors().First();
    //module.Import(ctor);
    CustomAttribute attribute = new CustomAttribute(ctor);
    attribute.ConstructorArguments.Add(new CustomAttributeArgument(module.TypeSystem.String, "InternalClass"));
    module.CustomAttributes.Add(attribute);
    module.Write(AssemblyName); //error
}
Run Code Online (Sandbox Code Playgroud)

-

public static TypeDefinition Add(ModuleDefinition targetModule)
{
    var type = targetModule.AddType("Namespace", "NewAttribute", TypeAttributes.Public | TypeAttributes.Class, targetModule.Import(typeof(Attribute)));
    var stringType = targetModule.TypeSystem.String;
    var nameField = type.AddField(stringType, "_name");
    var nameProp = type.AddSimpleProperty(stringType, "Name", nameField);

    // generate a constructor body
    var constructor = type.AddConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, targetModule.TypeSystem.Void, new[] { …
Run Code Online (Sandbox Code Playgroud)

c# reflection cil mono.cecil

6
推荐指数
1
解决办法
2876
查看次数

CIL unbox_any指令 - 奇怪的行为

.method public static void  Test<class T>(object A_0) cil managed
{
  // Code size       13 (0xd)
  .maxstack  1
  .locals init (!!T V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     !!T
  IL_0006:  unbox.any  !!T
  IL_000b:  stloc.0
  IL_000c:  ret
} // end of method DemoType::Test
Run Code Online (Sandbox Code Playgroud)

相同的C#代码是:

public static void Test<T>(object o) where T : class
{
    T t = o as T;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 为什么unbox.any被称为?如果你这样做

     var a = father as child 
    
    Run Code Online (Sandbox Code Playgroud)

    isinst intruction将调用而不是unbox.any,如果我将删除泛型定义并且我将尝试将(isinst)对象强制转换为某个类,则不会调用unbox.any.

  2. 也许因为泛型定义而调用unbox.any,所以在这种情况下unbox.any需要抛出NullReferenceException,因为isinst指令的答案为此转换返回null.请参阅unbox_any.如果您尝试运行此代码,您将看到没有抛出任何异常.

更新

我可以理解unbox_any因为对象类型参数,它尝试在isinst检查后将其强制转换为具体类型.也许仿制药也会影响.

我的问题是,为什么不在unbox.any中抛出异常,如果我们尝试unbox到T的obj是null?

文档说:"如果obj是一个空引用,则抛出NullReferenceException."

.net clr il cil nullreferenceexception

5
推荐指数
1
解决办法
258
查看次数

用于删除unbox_any的抖动逻辑

我正在调查这个C#代码的执行情况:

public static void Test<T>(object o) where T : class
{
    T t = o as T;
}
Run Code Online (Sandbox Code Playgroud)

等效的IL代码是:

.method public static void  Test<class T>(object A_0) cil managed
{
  // Code size       13 (0xd)
  .maxstack  1
  .locals init (!!T V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     !!T
  IL_0006:  unbox.any  !!T
  IL_000b:  stloc.0
  IL_000c:  ret
} // end of method DemoType::Test
Run Code Online (Sandbox Code Playgroud)

根据这个答案(不必要的unbox_any),任何人都可以向我解释一下Jitter在这里做的确切逻辑; 在这个特定的情况下,抖动究竟是如何决定忽略'unbox_any'指令的(理论上,根据msdn,当isinst指令产生null时应该抛出NullReferenceException,但这在实践中不会发生!)

更新

基于usr回答和Hans注释,如果obj是引用类型,castclass将被调用,因此,没有NRE.

但是下面这个案子呢?

static void Test<T>(object o) where T : new()
    { …
Run Code Online (Sandbox Code Playgroud)

.net c# clr optimization jitter

5
推荐指数
1
解决办法
182
查看次数