[英]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.