2009-11-25 4 views

ответ

6

Чтобы продолжить ответ Джона, сделать это вместо того, чтобы:

string username; 
if (myDic.TryGetValue("username", out username)) 
{ 
    user.Username = username; 
} 
3

Вы можете сделать это в VB, но не C#.

VB будет генерировать временную переменную (в стеке), передать ее адрес в значение out, а затем выполнить присвоение свойства после вызова метода.

Обычно VB делает это, потому что он делает много неявного материала повсюду. Так оно и работает.

С другой стороны, C#, как правило, избегает имплицитности как части своей философии. Вот почему, например, вам нужно добавить «out» на сайт вызова, чтобы получить параметры для работы, и почему он не поддерживает параметры «ref» для первого аргумента для методов расширения.

Здесь можно будет поддерживать свойства, используя явный синтаксис «out» на сайте вызова. Однако я считаю, что причина, по которой они этого не делают, заключается в том, что трюк, используемый VB, не ведет себя точно так же для свойств, как для полей. С полем назначение будет происходить сразу же там, где оно произошло внутри метода. Если в методе, читающем поле (при вызове метода на объекте), был другой код, он считывал новое значение поля, назначенное через выходной параметр.

С помощью свойств, использующих трюк VB, свойство не будет назначено до тех пор, пока метод не вернется. Это означает, что любой код, который считывал свойство сразу после назначения параметра out, считывал старое значение.

Вот простой пример того, что я имею в виду:

class C 
{ 
    private int m_bar; 

    public int Bar { get { return m_bar; } set { m_bar = value; }} 

    void foo(out int x) 
    { 
     x = 2; 
     Console.WriteLine(Bar); 
    } 

    void DoStuff() 
    { 
     foo(out m_bar); //outputs 2 
     Bar = 0; 
     //pretend this works 
     foo(out Bar); //outputs 0 
     Console.WriteLine(Bar); // outputs 2 
    } 
} 

Внутри DoStuff(), вы получите различное поведение для первого вызова Foo, чем вы бы от второго вызова обув, хотя большинство людей будут ожидайте, что они будут вести себя одинаково.

Как правило, C# пытается избежать таких вещей.

Это мое предположение, почему они не поддерживают его (спецификация просто говорит, что не поддерживает, на самом деле это не говорит почему).

Смежные вопросы