在c#中this和ref的等效功能 [英] Equivalent functionality of `this` and `ref` in c#
问题描述
如果我在一个类中有一个函数:
If I have a function within a class:
/* class snipped */
private void Expect(ref Utf8JsonReader reader, JsonTokenType t)
{
reader.Read();
/* snip */
}
由于对象被操纵而通过引用传递,这与静态帮助器函数有何不同:
Which is passed by reference since the object is being manipulated, is this any different to a static helper function:
/*static class snipped*/
static public void Expect(this Utf8JsonReader reader, JsonTokenType t)
{
reader.Read();
/* snip */
}
// call helper via reader.Expect(requiredToken)
我问如果使用 ref
时有任何看不见的细微差别,它会在 Utf8JsonReader
和 Memory< T>
在嵌套函数之间传递的对象.
I ask in the event of any unseen nuances when ref
is used, it is heavily in the code alongside Utf8JsonReader
and Memory<T>
objects passed down between nested functions.
我正在寻求重构(在这种情况下,对阅读器对象使用扩展方法会更好.)
I am looking to refactor (and would be far nicer using extension methods on the reader object in this case).
this
(外部类的扩展方法)和 ref
(通过函数之间的引用传递)在功能上是否等效吗?
Are this
(extension method on external class) and ref
(pass by reference between functions) functionally equivalent?
更新-需要 ref this
?
Update - ref this
required??
作为更新,仅使用 this
不起作用,在 ExpectNamedProperty
函数中,它将调用 reader.Expect
,但是返回对象时恢复.不知何故正在堆栈上制作副本,或者发生了什么事情.
As an update, simply using this
did not work, within ExpectNamedProperty
function it would call reader.Expect
but on returning the object would revert. Somehow a copy is being made on the stack or something is going on.
我什至不知道这是一个有效的组合, ref this
确实有效,而 this
仅不会修改.需要澄清的是不要做可怕的事情!
I didnt even know this was a valid combination, ref this
does work, whereas this
only does not modify. Need to clarify not doing something terrible!
public static void Expect(ref this Utf8JsonReader reader, JsonTokenType t)
{
reader.Read(); // this mutation is never passed back to caller
}
public static void ExpectNamedProperty(ref this Utf8JsonReader reader, string expectedPropertyName)
{
reader.Expect(JsonTokenType.PropertyName, expectedPropertyName);
// at this point it is as if the function above was never called
var foundPropertyName = reader.GetString();
if (foundPropertyName != StreamFieldNames.Event)
throw new JsonException($"expected {StreamFieldNames.Event} found {foundPropertyName} at position {reader.Position.GetInteger()}");
}
推荐答案
ref
很好.而 ref this
等效于/p的另一种形式
ref
is fine. And ref this
is equivalent to / another form of
ExtensionsClass.ExpectNamedProperty(参考阅读器)
ExtensionsClass.ExpectNamedProperty(ref reader)
与此同时,请勿在 中使用.
在这种情况下, in
会使性能变差.
Meanwhile, DO NOT USE in
.
in
makes performance worse in this case.
in
适用于 readonly结构
,而对于非只读结构,编译器会每次创建防御副本,该结构通常用于确保该结构是只读的.这会大大降低性能.
in
works perfectly for readonly struct
, whereas for non-readonly struct, the compiler creates defensive copy every time the struct is used to make sure the struct is readonly. This significantly degrades performance.
In your case, Utf8JsonReader
is a ref struct
, not readonly struct
.
请考虑以下示例:
private void ExpectWithIn(in Utf8JsonReader reader)
{
reader.Read();
}
private void ExpectWithRef(ref Utf8JsonReader reader)
{
reader.Read();
}
ExpectWithRef(ref reader);
ExpectWithIn(reader);
ExpectWithRef
的已编译IL:
// (no C# code)
IL_0000: nop
// reader.Read();
IL_0001: ldarg.1
IL_0002: call instance bool [System.Text.Json]System.Text.Json.Utf8JsonReader::Read()
IL_0007: pop
// (no C# code)
IL_0008: ret
ExpectWithIn
的已编译IL:
// (no C# code)
IL_0000: nop
// The compiler creates defensive copy to make sure reader variable is readonly
// The compiler repeats this for every use of reader variable
// so this is significant impact
// Utf8JsonReader utf8JsonReader = reader;
IL_0001: ldarg.1
IL_0002: ldobj [System.Text.Json]System.Text.Json.Utf8JsonReader
IL_0007: stloc.0
// utf8JsonReader.Read();
IL_0008: ldloca.s 0
IL_000a: call instance bool [System.Text.Json]System.Text.Json.Utf8JsonReader::Read()
IL_000f: pop
// (no C# code)
IL_0010: ret
Sergey Tepliakov具有一篇不错的文章解释了 in
修饰符以及何时使用它.
Sergey Tepliakov has a good article explaining the in
modifier and when to use it.
这意味着您永远不要像参数中那样传递非只读结构.几乎总是会使性能变差.
这篇关于在c#中this和ref的等效功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!