Параметр Out может не инициализироваться перед доступом

Почему код ниже

private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
{
    if(datasetsList == null)
        datasetsList=new List<WorkflowVariableDataSet>();
    datasetsList=new List<WorkflowVariableDataSet>();
    return datasetsList;
}

генерирует ошибку в первом выражении if:

Out parameter 'datasetsList' might not be initialized before accessing.

Я знаю, что в этот момент он должен быть неинициализирован, но слово might предполагает, что ошибка заключается в возможном доступе к неинициализированному объекту (когда он даже не доступен, это ссылка, которая проверяется). Ofc, что не происходит с ключевым словом ref, но мне любопытно, как эталонная проверка нарушает политику вне параметров.

ИЗМЕНИТЬ Я отредактировал вопрос и пример: в любом случае объект out будет инициализирован внутри метода. Возникает вопрос: ПОЧЕМУ неинициализированный объект не может быть равен нулю? Как это отличается от:

object o;
if(o==null)
    ...

Ответ 1

Ошибка компилятора CS0269

Использование параметра непризнанного выходного параметра 'Компилятор не смог убедитесь, что перед параметром out было присвоено значение; его значение может быть undefined при назначении. Обязательно присвойте значение перед тем как получить доступ к значению. если ты необходимо использовать значение переменной, переданной в, использовать параметр refвместо.

Так что рассматривайте out -параметр как неназначенный. Вы тот, кто несет ответственность.

Поэтому просто удалите if:

datasetsList = new List<WorkflowVariableDataSet>();

Если вы хотите обработать список, который передается этому методу, используйте ref intead (как было предложено выше):

Ответ 2

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

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

Итак, если мы рассмотрим:

private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
{
    if(_someBooleanField)
       datasetsList = null;
    if(datasetsList == null)
        datasetsList=new List<WorkflowVariableDataSet>();
    return datasetsList;
}

Здесь использование неинициализированного параметра может или не может произойти, но это означает, что он имеет ту же ошибку.

Что касается ошибки, то между этими двумя случаями действительно нет существенной разницы.

И поэтому сообщение об ошибке может использоваться, даже в тех случаях, когда оно всегда будет применяться.

Ответ 3

Аргументы вывода не должны быть инициализированы перед передачей, вызывающий метод должен назначать значение перед возвратом метода.

Изменен ваш код

 private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
            {
                return datasetsList = new List<WorkflowVariableDataSet>();
            }