首页 > 解决方案 > c# 中 `this` 和 `ref` 的等效功能

问题描述

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

/* class snipped */
private void Expect(ref Utf8JsonReader reader, JsonTokenType t)
{
    reader.Read();
    /* snip */
}

由于正在操作对象,因此通过引用传递,这与静态辅助函数有什么不同:

/*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>对象在嵌套函数之间传递。

我正在寻找重构(在这种情况下,在阅读器对象上使用扩展方法会更好)。

this(外部类的扩展方法)和ref(函数之间的引用传递)在功能上是否等效?

更新 -ref this需要??

作为更新,简单地使用this不起作用,在ExpectNamedProperty它会调用的函数内reader.Expect但在返回对象时会恢复。不知何故,正在堆栈上制作副本或正在发生某些事情。

我什至不知道这是一个有效的组合,ref this确实有效,而this只是不修改。需要澄清不做可怕的事情!

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()}");
}

标签: c#.netthis

解决方案


你可以写很多扩展方法,但它们真的相关吗?在扩展方法中编写所有内容都会生成意大利面条式代码。

我会选择in关键字。inover的优点ref是您无法修改参数,但不会获得副本(如“正常”参数)。您也可以将只读字段作为in参数传递。

private void Expect(in Utf8JsonReader reader, in JsonTokenType t)
{
   reader.Read();
    /* snip */
}

推荐阅读