在c#中this和ref的等效功能 [英] Equivalent functionality of `this` and `ref` in c#

查看:111
本文介绍了在c#中this和ref的等效功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在一个类中有一个函数:

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屋!

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