将null分配给类的实例和声明只是有什么区别

Ser*_*nko 4 c# null declaration

我试图理解为类的实例赋值null和只是声明这个类之间是否有任何区别.举个例子,我有一个课程:

public class MyClass
{
    public string FirstProperty { get; set; }
    public int SecondProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我正在创建该类的两个实例:

MyClass Instance1 = null;
MyClass Instance2;   // just declaration
Run Code Online (Sandbox Code Playgroud)

有什么区别Instance1Instance2
是的,是否安全,Instance2只有声明是一个好习惯?

Jon*_*nna 6

然后我正在创建该类的两个实例:

你没有创建任何实例.如果创建实例,则创建两个放置实例的位置.你明确表示的第一个没有实例,第二个没有实例.

有什么区别Instance1Instance2

这取决于你在哪里做到了.

如果该代码在a之内class或者struct你已经创建了两个字段,那么这两个字段都将被设置为null最初,除非构造函数执行其他操作.

如果你在方法中包含那些代码(包括构造函数或属性访问器),那么你有两个局部变量(虽然惯例是在这里使用小写).

第一个被设置为null,你可以用它做有效处理null的事情(将它传递给一个方法[虽然如果它拒绝接受null 可能抛出异常)将它与某些东西进行比较以确认它是确实为null或者确实与真正具有实例的东西相同.

第二个尚未分配,因此除了分配某些内容(无论是null还是实例)之外,执行任何操作都是非法的.在确定设置之前做任何事情的任何尝试都将是编译器错误.例如:

MyClass Instance2;
if (valueThatJustHappensToAlwaysBeTrue)
{
   Instance2 = new MyClass();
}
bool isNull = Instance2 == null; // Error! Not guaranteed to be assigned strongly enough for the compiler to know.
Run Code Online (Sandbox Code Playgroud)

是的,是否安全,Instance2只有声明是一个好习惯?

在可能的情况下,尽可能接近第一个任务(初始化),理想情况下同时宣布这是一个好习惯:

MyClass instance = new MyClass();
Run Code Online (Sandbox Code Playgroud)

但是,如果您有一些不同的可能路径,例如:

MyClass instance;
if (boolValue)
{
   instance = new MyClass(1); // Yes, I know there's no int-taking ctor on your class, but it defeats the argument when the bare constructor is the only one available, so let's say there is.
}
else if (otherBoolValue)
{
   throw new SomeException();
}
else if (someIntValue > 42)
{
   instance = new MyClass(3);
}
else
{
   instance = new MyClass(9);
}
Run Code Online (Sandbox Code Playgroud)

现在,用未初始化的方式来到这个链的末端是不可能的instance.它将被设置,或者将抛出异常.如果我们认为开始时可能"更安全",MyClass instance = null那么我们可能会隐藏一个错误.上面的逻辑意味着为每个路径分配一些东西,并且由于规则不能使用不能保证分配的实例,那么错误会导致编译器错误,并且错误很明显.如果它被分配给一个"占位符"null,那么从这样的错误开始就不会那么明显,并且可能导致错误.

所以在像裸声明的情况下更好.

但是,如果可能的话,总是更好地避免使用复杂的逻辑,因此那些复杂的链条应该是罕见的.在其他情况下,在同一点上声明和分配的方式意味着你在错误可能滑入的两者之间没有差距.


Ren*_*ogt 5

在您的示例中,您没有创建任何实例.你声明了两个变量.

到你明确指定 的第一个null.到第二个你不分配任何东西.因此它包含默认值,null用于引用类型.1

从技术上讲,这两个变量之间现在没有区别.但是如果您尝试使用值,编译器可能会引发错误,因为编译器不允许使用未初始化的变量:Instance2

MyClass Instance1 = null;
MyClass Instance2;
Console.WriteLine(Instance1); // fine
Console.WriteLine(Instance2); // raises error CS0165
Run Code Online (Sandbox Code Playgroud)

1正如stuartd和Kyle评论的那样,编译器根本不会初始化局部变量,这解释了错误.在分配一个变量之前,不能依赖具有任何特定值的变量,无论是否null是创建的实例MyClass.字段和属性初始化为类型的默认值(null对于引用类型).