繁体   English   中英

为什么不能将值类型的“ this”装箱?

[英]Why can't “this” for value types be boxed?

因此,我希望能够模仿C#中VB的“具有”功能,并通过StackOverflow遇到了一个相当聪明的解决方案:

public static x with<x>(this x item, Func<x,x> f)
{
    item = f(item);
    return item;
}

实现您将执行以下操作:

myObject = myObject.with(myVariable => {
    //do things
});

但是,当我尝试在具有该结构的字段之一的结构中实现此功能时,遇到了麻烦。 它说:“ 结构内部的匿名方法无法访问'this'的成员 。”

我对此进行了一些研究,并找到了该问题的答案, 该问题最终指出,不能将值类型的“ this”装箱。 在研究了装箱对C#意味着什么之后,考虑到该函数的参数没有定义的类型,这是有道理的。

我的问题是, 为什么不能对值类型的“ this”进行装箱?

我想您知道有关在构造过程中设置属性的知识,这是相似的(并且更常见于C#)?

class MySpecialClass
{
   public string Property1 {get;set;}
   public int Length {get;set;}
   public float Width {get;set;}
}

var p = new MySpecialClass
{
  Property1 = "PropertyValue",
  Length = 12,
  OtherThing = 1.234F
};

此处的主要问题是,在一个方法struct ,意思this不是一个 (即你的价值SomeStruct ),而是一个参考值 (α ref SomeStruct ,或者有效的in SomeStruct在的情况下, readonly struct )。

您不能将这种形式的托管指针装箱-运行时不支持这种情况。 托管指针仅应位于堆栈上。 实际上,当前您甚至无法在无法逃避堆栈的自定义ref struct中拥有ref SomeStruct字段。

编译器可以通过假装这样做来作弊 -即通过将引用中的托管指针从ref SomeStruct 解引用SomeStruct并创建捕获上下文,其中this捕获上下文被解释为“我们之前取消引用的SomeStruct ”,但是...然后编译器可以不能保证相同的行为和结果(实际上,我怀疑在readonly struct方案中可能会遇到这种情况,但是...不引入这种细微差别可能会更容易)。

相反,编译器建议您有效地手动执行上述步骤; 由于编译器不再this处理,因此它不再必须假装尊重处理this结果的通常结果,而只需要保证值的显式取消引用副本的行为即可。 这就是为什么建议(至少在当前的编译器版本上)的原因:

考虑将“ this”复制到匿名方法,lambda表达式或查询表达式之外的局部变量中,并使用局部变量代替。

因此,大多数lambda,局部方法等可以通过以下务实步骤实现:

MyStruct copy = this; // dereference

然后在您的λ/本地方法的/ etc:而非触摸Something又名this.Something -触摸copy.Something 它现在唯一的copy是被包含在捕捉范围内,并copy不被约束ref SomeStruct规则(因为:它不是一个ref SomeStruct -这是一个SomeStruct )。

,然而,是不是意味着如果你的意图是变异this (并且具有明显的原地的,而不是作为一个返回值),那么它将无法工作。 您只需要更改副本 (即copy )。 这正是编译器将不得不如果撒了谎反正做,但至少现在拷贝步骤(解引用)是明确的,可见你的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM