Следующий код недопустим:
public struct MyStruct
{
public MyStruct(int a, int b)
{
this.a = a;
this.b = b;
}
public int a;
public int b;
}
//now I want to cache for whatever reason the default value of MyStruct
MyStruct defaultValue;
...
if (foo != defaultValue) //use of unassigned variable...
Очевидно, что все должно быть сделано:
MyStruct defaultValue = default(MyStruct) //or new MyStruct();
...
if (foo != defaultValue) //compiler is happy
Но также допускается следующее (Iя не знал об этом и случайно наткнулся на него):
MyStruct defaultValue;
defaultValue.a = 0;
defaultValue.b = 0;
...
if (foo != defaultValue) //legal
Я думаю, компилятор проверяет, что все поля struct
были инициализированы, и поэтому позволяет этому коду компилироваться.Тем не менее я нахожу это путающим с тем, как работает остальная часть языка.В конце концов, вы в основном используете неназначенную переменную в C # способе видеть вещи.
Вещи становятся еще более запутанными, если учесть следующий код:
public struct MyStruct
{
public MyStruct(int a, int b)
{
this.a = a;
this.b = b;
this.c = (a + b).ToString();
}
public int a;
public int b;
internal string c;
}
Следующий код недопустимпотому что в этом случае мы не присвоили все видимые поля:
MyStruct defaultValue;
defaultValue.a = 0;
defaultValue.b = 0;
...
if (foo != defaultValue) //use of unassigned variable...
Visible является ключевым словом здесь, потому что, если MyStruct
должны были быть определеныв ссылочной сборке c
не будет видимым , и компилятор не будет жаловаться, и предыдущий код будет совершенно корректным.Снова сбивает с толку.
Может кто-нибудь объяснить, почему это позволило инициализировать struct
в C # таким образом?Почему бы не запретить это полностью, чтобы при работе с любым типом значения в языке был более унифицированный опыт?
EDIT 1 : я допустил ошибку в последнем примере.Компилятор будет счастлив, только если поле not visible имеет тип reference .Еще более запутанно.Является ли этот последний случай известной ошибкой в компиляторе или есть разумная причина, по которой он работает так, как работает?
Изменен последний пример на допустимый.
EDIT 2: Я все еще немного озадачен тем, как работает инициализация value-type .Почему, например, не допускается следующее:
struct MyStruct
{
public int A { get; set; } //Auto-implemented property
public int B { get; set; } //Auto-implemented property
}
MyStruct defaultValue;
defaultValue.A = 0; //use of unassigned variable...
defaultValue.B = 0;
На мой взгляд, нет никаких сомнений в том, что все поля MyStruct
инициализированы.Я вижу причину, по которой это нельзя было бы разрешить, если бы свойства не были автоматически реализованы , поскольку вполне возможно, что установщики не гарантируют, что все поля установлены.Но в автоматически реализованных свойствах компилятор знает со 100% -ной уверенностью, что поля будут установлены, если свойства заданы (после всего кода, который генерирует для вас компилятор).
Наконец, небольшой теоретический случай, который, очевидно, не имеет практического применения:
struct MyUselessStruct
{
}
MyUselessStruct defaultValue;
Console.WriteLine(defaultValue.ToString()); //hehe did I get away with using an unassigned variable?
Тогда почему это не разрешено:
Object object;
if (object == null) .... //use of unassigned variable
Я нахожу оба случая схожими по концепции иЯ ожидаю, что они оба будут работать одинаково в C #.Я до сих пор не понимаю, почему это, казалось бы, бесполезное различие в способе инициализации переменных тип значения и его практическое применение (помимо несоответствий, которые я объяснил в первой части моего вопроса)