Почему свойство не может быть передано как параметр out? - PullRequest
11 голосов
/ 27 января 2011

Например:

    int? qID= null;

    answer.QuestionID = int.TryParse(lblID.Text, out qID.Value) ? qID : null; //Error: Property or Indexer may not be passed as an out ot ref parameter.

Из документации Microsoft говорится, что:

"Переменная, передаваемая в качестве аргумента out, не должна быть инициализирована. Однако параметру out необходимо присвоить значение до возврата метода."

и затем:

"Свойство не является переменной и не может быть передано как выходной параметр.

Итак, что было причиной того, что в базовой платформе .net была запрещена установка свойства объекта через out? Значение out также не обязательно должно быть ссылочным объектом - вполне допустимо использовать тип значения. Так почему бы и нет?

Ответы [ 5 ]

15 голосов
/ 27 января 2011

Это допустимо в VB, но не в C # ... VB эффективно создает временную локальную переменную для вас, вызывает метод, передающий в качестве аргумента локальную переменную, а затем устанавливает свойство со значением локальной переменной , C # обычно не скрывает такого рода вещи для вас.

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

Таким образом, либо компилятор должен подделать его с помощью временной переменной согласно VB, либо запретить его согласно C #. Лично я предпочитаю подход C # - в противном случае он выглядит , как будто каждый раз, когда метод присваивает значение параметру out, свойство устанавливается - что, конечно, не так.

10 голосов
/ 27 января 2011

Свойство - это просто пара функций с именами get_Something и set_Something.
Параметр out принимает ссылку на поле или переменную; не имеет смысла передавать пару функций.

VB.Net может передавать свойства как ByRef параметры ; компилятор генерирует временную переменную и повторно присваивает свойство переменной после вызова метода.

Однако даже VB.Net не может обработать ваш случай, потому что свойство Nullable<T>.Value доступно только для чтения.

2 голосов
/ 27 января 2011

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

Рассмотрим тип Foo со свойством Bar;использование этого свойства в качестве параметра out по сути аналогично этому:

Foo foo = new Foo();
SomeFunction(out foo.get_Bar());

Очевидно, что значение не может быть присвоено foo.get_Bar()!

2 голосов
/ 27 января 2011

Поскольку свойство является синтаксическим сахаром для метода get и set, которые генерируются компилятором.

2 голосов
/ 27 января 2011
int qID;

if (int.TryParse(lblID.Text, out qID))
{
  answer.QuestionID =  qID;
}
else
{
  answer.QuestionID = null;
}

вот фактическая реализация:

[System.Security.SecuritySafeCritical]  // auto-generated
    internal unsafe static Boolean TryParseInt32(String s, NumberStyles style, NumberFormatInfo info, out Int32 result) {

        Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; 
        NumberBuffer number = new NumberBuffer(numberBufferBytes);
        result = 0; 

        if (!TryStringToNumber(s, style, ref number, info, false)) {
            return false; 
        }

        if ((style & NumberStyles.AllowHexSpecifier) != 0) {
            if (!HexNumberToInt32(ref number, ref result)) { 
                return false;
            } 
        } 
        else {
            if (!NumberToInt32(ref number, ref result)) { 
                return false;
            }
        }
        return true; 
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...