Используйте принцип ref в новом не нулевом тесте - PullRequest
2 голосов
/ 02 октября 2019

Я не знаю, как именно это называется, но сейчас я буду называть это «не нулевым тестом». В 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 тоже не существует. Так есть ли какой-нибудь способ, которым вы можете сделать это, или есть что-то, что будет против этого?

1 Ответ

2 голосов
/ 02 октября 2019

Шаблон, который вы используете, является шаблоном свойства из функции сопоставления с шаблоном C # 8 .

Шаблон свойства позволяет сопоставлятьсвойства исследуемого объекта.

Если я правильно понял ваш вопрос, вы хотели бы не только получить значение свойства, но и возможность изменить это значение в сопоставляемом объекте.

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

Чтобы семантика ref работала, она должна поддерживаться языком и компилятором.

Однако C # не позволяет использовать ref со свойством - и этоверно для любой версии C #. Причина очевидна: ваше свойство get-set Bar (как и любое другое свойство C #) будет скомпилировано с двумя методами: get_Bar и set_Bar. Таким образом, на самом деле у вас есть метод, а не значение - таким образом, вы не можете ref значение, которое возвращает метод (хорошо, есть ref return s, но они не применяются к получателям свойств).

...