Инициализация полей экземпляра по сравнению с локальными переменными

У меня было несколько проблем с этим кодом, получая элемент не foung исключения. Только для ссылки, случалось так, что мне было нужно мое пространство имен, включенное в DataTemplate...

private DataTemplate Create(Type type)
        {
            string xaml = @"<DataTemplate 
                xmlns=""http://schemas.microsoft.com/client/2007""
                xmlns:controls=""clr-namespace:" + type.Namespace + @";assembly=" + type.Namespace + @""">
                <controls:" + type.Name + @"/></DataTemplate>";
            return (DataTemplate)XamlReader.Load(xaml);
        }
18
задан svick 20 January 2013 в 01:11
поделиться

7 ответов

For local variables, the compiler has a good idea of the flow - it can see a "read" of the variable and a "write" of the variable, and prove (in most cases) that the first write will happen before the first read.

This isn't the case with instance variables. Consider a simple property - how do you know if someone will set it before they get it? That makes it basically infeasible to enforce sensible rules - so either you'd have to ensure that all fields were set in the constructor, or allow them to have default values. The C# team chose the latter strategy.

29
ответ дан 30 November 2019 в 07:03
поделиться

It is governed by Definite Assignment rules in C#. Variable must be definitely assigned before it is accessed.

5.3 Definite assignment

At a given location in the executable code of a function member, a variable is said to be definitely assigned if the compiler can prove, by a particular static flow analysis (§5.3.3), that the variable has been automatically initialized or has been the target of at least one assignment.

5.3.1 Initially assigned variables

The following categories of variables are classified as initially assigned:

  • Static variables.

  • Instance variables of class instances.

  • Instance variables of initially assigned struct variables.

  • Array elements.

  • Value parameters.

  • Reference parameters.

  • Variables declared in a catch clause or a foreach statement.

5.3.2 Initially unassigned variables

The following categories of variables are classified as initially unassigned:

  • Instance variables of initially unassigned struct variables.

  • Output parameters, including the this variable of struct instance constructors.

  • Local variables, except those declared in a catch clause or a foreach statement.

6
ответ дан 30 November 2019 в 07:03
поделиться

When a chunk of memory is allocated for a new object instance, the runtime writes zeros across the entire block, ensuring that the new object starts at a known state - this is why integers default to 0, doubles default to 0.0, pointers & object references to null, and so on.

It would be possible, in theory, to do the same to stack frames allocated as as part of method calls. The overhead, though would be high - it would drastically slow down calls to other methods, and therefore isn't attempted.

2
ответ дан 30 November 2019 в 07:03
поделиться

Instance variables have a default value. From the C# 3.0 specification:

5.1.2.1 Instance variables in classes

An instance variable of a class comes into existence when a new instance of that class is created, and ceases to exist when there are no references to that instance and the instance’s finalizer (if any) has executed.

The initial value of an instance variable of a class is the default value (§5.2) of the variable’s type.

For the purpose of definite assignment checking, an instance variable is считается изначально назначенным.

1
ответ дан 30 November 2019 в 07:03
поделиться

Это ограничение компилятора. Компилятор пытается помешать вам использовать неназначенные переменные везде, где это возможно, что хорошо, поскольку использование неинициализированных переменных было обычным источником ошибок в старом коде C.

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

1
ответ дан 30 November 2019 в 07:03
поделиться

Неявный конструктор инициализирует переменную экземпляра за вас. Даже когда вы указываете c'tor, но не инициализируете поле, это делается за вас как часть создания объекта в куче. Это не относится к локальным переменным стека.

1
ответ дан 30 November 2019 в 07:03
поделиться

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

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

1
ответ дан 30 November 2019 в 07:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: