拳击发生在C# [英] Boxing Occurrence in C#

查看:225
本文介绍了拳击发生在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想收集所有的在C#中出现拳击情况:

I'm trying to collect all of the situations in which boxing occurs in C#:


  • 转换任何值类型为 System.Object的类型:

struct S { }
object box = new S();


  • 转换任何值类型为 System.ValueType 类型:

    struct S { }
    System.ValueType box = new S();
    


  • 将任何枚举类型为 System.Enum 类型:

    enum E { A }
    System.Enum box = E.A;
    


  • 转换任何类型的值到接口的参考:

  • Converting any value type into interface reference:

    interface I { }
    struct S : I { }
    I box = new S();
    


  • 非恒定值类型在C#字符串连接:

  • Non-constant value types in C# string concatenation:

    char c = F();
    string s1 = "char value will box" + c;
    


  • 这是值类型的实例方法创建委托:

  • Creating delegate from value type instance method:

    struct S { public void M() {} }
    Action box = new S().M;
    


  • 调用价值类型的非重写虚拟方法:

  • Calling non-overridden virtual methods on value types:

    enum E { A }
    E.A.GetHashCode();
    


  • 对象的可选参数值类型的默认值输入:

  • Optional parameters of object type with value type default values:

    void M([Optional, DefaultParameterValue(42)] object o);
    M(); // boxing at call-site
    


  • 检查约束泛型类型的值

    bool M<T>(T t) => t != null;
    string M<T>(T t) => t?.ToString(); // ?. checks for null
    M(42);
    


  • 不受约束或结构泛型类型与
  • 类型的测试值为 / 运营商:

  • Type testing value of unconstrained or struct generic type with is/as operators:

    bool M<T>(T t) => t is int;
    int? M<T>(T t) => t as int?;
    IEquatable<T> M<T>(T t) => t as IEquatable<T>;
    M(42);
    


  • 是否有拳击的更多的情况下,也许隐藏的,你知道吗?

    Are there any more situations of boxing, maybe hidden, that you know of?

    推荐答案

    这是一个很大的问题!

    拳击整整一个原因发生:当我们需要一个值类型的参考。你上市的一切属于这一规则。

    Boxing occurs for exactly one reason: when we need a reference to a value type. Everything you listed falls into this rule.

    例如,因为对象是引用类型,铸造一个值类型对象要求为值类型,这会导致拳击的参考。

    For example since object is a reference type, casting a value type to object requires a reference to a value type, which causes boxing.

    如果你想列出所有可能的情况下,您还应该包括衍生物,如返回从返回对象或一个接口类型的方法的值类型,因为这个自动转换值类型的对象/接口。

    If you wish to list every possible scenario, you should also include derivatives, such as returning a value type from a method that returns object or an interface type, because this automatically casts the value type to the object / interface.

    顺便说一句,你敏锐地也确定了字符串连接情况下,从铸造到对象派生的。 +运算符是由编译器对字符串的concat方法,它接受你传递值类型的对象的调用翻译,所以铸造对象,因此拳击发生。

    By the way, the string concatenation case you astutely identified also derives from casting to object. The + operator is translated by the compiler to a call to the Concat method of string, which accepts an object for the value type you pass, so casting to object and hence boxing occurs.

    多年来,我一直劝开发商要记住拳击单一的原因(我上面指定的),而不是记住每一个情况下,由于名单很长,很难记住。这也促进了什么IL $ C $的理解c中的编译器为我们的C#code(例如+上串屈服于String.Concat通话)。当傻冒怀疑什么,编译器生成,如果发生拳击,你可以使用IL反汇编程序(Ildasm.exe)。通常情况下,你应该寻找箱子运code(有正当虽然IL不包括箱运code,下面更详细拳击甚至可能会出现一种情况)。

    Over the years I’ve always advised developers to remember the single reason for boxing (I specified above) instead of memorize every single case, because the list is long and hard to remember. This also promotes understanding of what IL code the compiler generates for our C# code (for example + on string yields a call to String.Concat). When your’e in doubt what the compiler generates and if boxing occurs, you can use IL Disassembler (ILDASM.exe). Typically you should look for the box opcode (there is just one case when boxing might occur even though the IL doesn't include the box opcode, more detail below).

    不过,我同意一些拳击事件不太明显。您列出的其中之一:调用值类型的非重写的方法。其实,这是另一个原因不太明显:当您检查IL code你没有看到箱子运code,但约束运code,所以即使在IL不是很明显拳击发生!我不会进入细节有为什么要这个答案变得更长prevent ...

    But I do agree that some boxing occurrences are less obvious. You listed one of them: calling a non-overridden method of a value type. In fact, this is less obvious for another reason: when you check the IL code you don’t see the box opcode, but the constraint opcode, so even in the IL it’s not obvious that boxing happens! I won't get into the exact detail why to prevent this answer from becoming even longer...

    有不太明显的拳击另一种情况是调用从结构的基类方法时。例如:

    Another case for less obvious boxing is when calling a base class method from a struct. Example:

    struct MyValType
    {
        public override string ToString()
        {
            return base.ToString();
        }
    }
    

    下面的ToString被覆盖,所以呼吁MyValType的ToString不会产生拳。然而,实现调用基的ToString和使拳击(检查IL!)。

    Here ToString is overridden, so calling ToString on MyValType won’t generate boxing. However, the implementation calls the base ToString and that causes boxing (check the IL!).

    顺便说一下,这两个非显而易见的拳击方案也从上述单一的规则推导。当一个方法是在基类值类型的引用,必须有东西在这个关键字来引用。由于基类的值类型是(总是)引用类型,在这个关键字必须引用引用类型,所以我们需要一个值类型的引用,使拳的发生是由于单一的规则。

    By the way, these two non-obvious boxing scenarios also derive from the single rule above. When a method is invoked on the base class of a value type, there must be something for the this keyword to refer to. Since the base class of a value type is (always) a reference type, the this keyword must refer to a reference type, and so we need a reference to a value type and so boxing occurs due to the single rule.

    下面是直接链接到我的网上.NET课程节详细讨论拳击: http://motti.me/mq

    Here is a direct link to the section of my online .NET course that discusses boxing in detail: http://motti.me/mq

    如果你只对更高级的场景拳击感兴趣这里是一个直接链接存在(虽然链接一旦讨论更基本的东西,上面会带你去以及):的 http://motti.me/mu

    If you are only interested in more advanced boxing scenarios here is a direct link there (though the link above will take you there as well once it discusses the more basic stuff): http://motti.me/mu

    我希望这有助于!

    Motti

    这篇关于拳击发生在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆