在新的非空测试上使用 ref 原则

Use the ref principle on the new not null test

我不知道它到底叫什么,但现在我将它称为 'not null test'。在 C# 8 中有一个新的行为允许测试一个对象是否不为空,例如:

Foo foo = new Foo();

if(foo is { })
{
    //foo is not null
}

您还可以从此对象中提取属性:

public class Foo
{
    public int Bar { get; set; }
}

Foo foo = new Foo();

if(foo is { Bar: var bar })
{
    //Foo is not null and bar contains the value of the property of the foo instance
}

到目前为止一切顺利,但我想它类似于这样的东西:

public bool GetBar(Foo foo, out int bar)
{
    if(foo is null)
    {
        return false;
    }

    bar = foo.Bar;
    return true;
}

可以这样使用:

Foo foo = new Foo();

if(GetBar(foo, out var bar))
{
    //Foo is not null and bar contains the value of the property of the foo instance
}

现在我的实际问题是:有什么方法可以使用 ref 的行为吗?看起来像这样:

if(foo is { Bar: ref var bar })
{
    //Foo is not null and bar contains the value of the property of the foo instance
}

如果这不存在我会理解,因为 out ref 也不存在。那么有什么办法可以做到这一点,或者有什么反对的吗?

您使用的模式是来自 C#8 pattern matching feature.

属性 模式

The property pattern enables you to match on properties of the object examined.

如果我没答错你的问题,你不仅希望获得 属性 值,而且希望能够更改匹配对象中的该值。

if (foo is { Bar: ref var bar })
{
    bar = 42; // now foo.Bar is 42 too
}

为了使 ref 语义起作用,它必须得到语言和编译器的支持。

但是,C# 不允许您将 ref 与 属性 一起使用 - 对于任何 C# 版本都是如此。原因很明显:您的 get-set 属性 Bar(与任何其他 C# 属性 一样)将被编译为两种方法:get_Barset_Bar。所以实际上你有一个方法,而不是一个值 - 因此,你不能 ref 一个方法 returns 的值(好吧,有 ref returns,但那些不适用属性 吸气剂)。