Есть ли сокращенный способ возврата значений, которые могут быть нулевыми?

Как написать стенографию следующего сценария?

get
{
    if (_rows == null)
    {
        _rows = new List<Row>();
    }

    return _rows;
}

Ответ 1

Использование оператора с нулевой связью (??):

get 
{ 
     _rows = _rows ?? new List<Row>(); 
     return _rows; 
}

ИЛИ (менее читаемый):

get { return _rows ?? (_rows = new List<Row>()); }

оператор называется нуль-коалесцирующим оператором. Он возвращает левый операнд, если операнд не равен нулю; в противном случае он возвращает правый операнд.

Ответ 2

Это ленивый шаблон инициализации, поэтому простым способом было бы использовать класс Lazy <T> .

class Foo
{
    Lazy<List<Row>> _rows;

    public Foo()
    {
        _rows = new Lazy(() => new List<Row>());
    }

    public List<Row> Rows
    {
        get { return _rows.Value; }
    }
}

Это имеет дополнительное преимущество в том, что он не "загрязняет" геттер логикой инициализации.

Ответ 3

Я предлагаю тернарный оператор

get {
  return _rows == null ? _rows = new List<Row>() : _rows;
}

Или, поскольку пустой List<Row> не приносит больших издержек, почему бы не избавиться от явного поля _row и реализовать свойство только для чтения (синтаксис С# 6.0):

public IList<Row> Rows {get;} = new List<Row>();

Ответ 4

Вот лучшая идея: Предотвратить _rows от когда-либо null.

Сделайте свой конструктор инициализацией переменной:

public MyClass()
{
    this._rows = new List<Row>();
}

а затем ваше свойство просто

get
{
    return this._rows;
}

Убедитесь, что если вам нужно "очистить" переменную, вы всегда вызываете ее метод Clear или назначаете новый пустой список вместо назначения null. Может быть, кодировать эту операцию в методе, если вам действительно нужно сделать ее понятной и последовательной во всем классе.

Это гораздо логичнее. Если ваша переменная никогда не должна быть null, она никогда не должна быть null. Он также аккуратно избегает как условного, так и проблемы с состоянием изменения геттера.

Ответ 5

List<Row> _rows;
public List<Row> Rows => _rows ?? (_rows = new List<Row>());

Ответ 6

Как говорили другие, вы можете использовать оператор с нулевым коалесцированием в этом сценарии.

get
{
    return _rows ?? (_rows = new List<Row>());
}

Стоит отметить, что это изменение, которое ReSharper отлично подходит для предложения (они называют это quick-fix).

В вашем примере он поместит небольшую кривую в оператор if. Наведение курсора на него показывает предложение о том, как можно изменить/упростить код.

Преобразовать в '??' Выражение

Несколько кликов позже, и это изменение реализовано.

введите описание изображения здесь

Ответ 7

Как это, например:

get{ return _rows ?? (_rows = new List<Row>()); }

Ответ 8

Если вы хотите, чтобы ваш код вел себя как ваш текущий код, лениво инициализируя ваше фоновое поле при доступе к ресурсу, то да, вы можете сделать его короче. Вы можете переименовать свое фоновое поле, так как в ответе уже используется ??, чтобы поместить все в одно выражение, и когда у вас есть это одно выражение, используйте синтаксис нового синтаксиса С# 6, чтобы избежать записи get и return:

List<Row>_;List<Row> Rows=>_??(_=new List<Row>());

Надеюсь, задолго до того, как вы дойдете до этого момента, вы увидите, что вы превратили простой в понимании код, который делает именно то, что вы хотите, в ужасный беспорядок, который вы никогда не захотите поддерживать.

Просто сохраните свой код в точности так, как есть. Вы можете сделать его короче, как показано, но это не делает его лучше.

Если проблема в том, что для записи требуется больше времени, потому что вы продолжаете вводить один и тот же код снова и снова, многие IDE предоставляют некоторую функцию для вставки шаблонов, фрагментов или любого другого термина, который они используют для него. Это позволяет вам определить что-то вдоль линий

{Type} {Field};
public {Type} {Property} {
  get {
    if ({Field} == null) {
      {Field} = new {Type}();
    }
    return {Field};
  }
}

где ваш редактор затем предложит вам указать {Type}, {Field}, {Property}, не вводя его снова каждый раз.

Ответ 9

return _rows ?? (_rows = new List<Row>());

Ответ 10

Если вы действительно хотели его укоротить, я просто удалю лишние скобки.

    get
    {
        if (_rows == null)
            _rows = new List<Row>();

        return _rows;
    }

Ответ 11

Вы можете сделать это одним из следующих способов:

  • Условный оператор (?:)
  • Оператор Null-coalescing (??)

С условным оператором

get {
  return _rows == null ? new List<Row>() : _rows;
}

Оператор Null-coalescing

get { 
  return _rows ?? new List<Row>(); 
}