我试图理解将null分配给类的实例与仅声明此类之间是否存在任何区别。举个例子,我有一个班级:
//
// Define Start Underline and Stop Underline tokens
START_UNDERLINE : "SomeWordToken(s) possibly \uxxx values";
STOP_UNDERLINE : "SomeOtherToken(s) possibly \uxxx values";
DIGITS : [0-9]+
UNDERLINED_DIGITS : START_UNDERLINE DIGITS STOP_UNDERLINE;
enter_underline : START_UNDERLINE;
exit_underline : STOP_UNDERLINE;
然后我创建了两个类的实例:
public class MyClass
{
public string FirstProperty { get; set; }
public int SecondProperty { get; set; }
}
MyClass Instance1 = null;
MyClass Instance2; // just declaration
和Instance1
之间有什么区别吗?
是的,是否安全,只有Instance2
声明是一个好习惯?
答案 0 :(得分:6)
然后我创建了两个类的实例:
您没有创建任何实例。如果创建实例,则创建两个放置实例的位置。你明确说过的第一个没有实例,第二个没有实例。
Instance1
和Instance2
之间有什么区别吗?
这取决于你在哪里做到了。
如果该代码位于class
或struct
之内,那么您创建了两个字段,这两个字段最初都将设置为null
,除非构造函数执行其他操作。< / p>
如果你在方法中包含那些代码(包括构造函数或属性访问器),那么你有两个局部变量(虽然惯例是在这里使用小写)。
第一个被设置为null,你可以用它做一些有效的null(把它传递给一个方法[虽然它可能如果拒绝接受null则会抛出异常)将它与某些东西进行比较,以确认它确实是空的,或者确实与真正具有实例的东西相同。
第二个尚未分配,因此除了分配某些内容(无论是null还是实例)之外,执行任何操作都是非法的。在确定设置之前做任何事情的任何尝试都将是编译器错误。 E.g:
MyClass Instance2;
if (valueThatJustHappensToAlwaysBeTrue)
{
Instance2 = new MyClass();
}
bool isNull = Instance2 == null; // Error! Not guaranteed to be assigned strongly enough for the compiler to know.
是的,它是否安全,让
Instance2
只有声明是一个好习惯?
如果可能的话,尽可能接近第一个作业(初始化),理想情况下同时宣布这是一个好习惯:
MyClass instance = new MyClass();
但是,如果您有一些不同的可能路径,例如:
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);
}
现在,使用未初始化的instance
无法到达此链的末尾。它将被设置,或者将抛出异常。如果我们认为从MyClass instance = null
开始可能会“更安全”,那么我们可能会隐藏一个错误。上面的逻辑意味着为每个路径分配一些东西,并且由于规则不能使用不能保证分配的实例,那么错误会导致编译器错误,并且错误很明显。如果它被分配给一个“占位符”null,从这个错误开始就不会那么明显,并且可能会导致错误。
所以在像裸声明的情况下更好。
但是,尽管如此,在可能的情况下总是更好地避免使用复杂的逻辑,因此那些复杂的链条应该是罕见的。在其他情况下,在同一点上声明和分配的方式意味着你可以在两者之间没有差距,而错误可能会出现。
答案 1 :(得分:5)
在您的示例中,您没有创建任何实例。您声明了两个变量。
首先明确分配 null
。到第二个你不分配任何东西。因此它包含默认值,对于引用类型是null
。 1
从技术上讲,这两个变量的值之间没有区别。但是如果您尝试使用Instance2
的值,编译器可能会引发错误,因为编译器不允许使用未初始化的变量:
MyClass Instance1 = null;
MyClass Instance2;
Console.WriteLine(Instance1); // fine
Console.WriteLine(Instance2); // raises error CS0165
1 正如stuartd和Kyle评论的那样,编译器根本不会初始化局部变量,这解释了错误。在分配一个变量之前,不能依赖具有任何特定值的变量,无论是null
还是已创建的MyClass
实例。字段和属性初始化为类型的默认值(null
用于引用类型。)
答案 2 :(得分:1)
null
关键字是表示null
引用的文字,不引用任何对象。 null
是引用类型变量的默认值。普通值类型不能是null
。
示例:强>
class Program
{
class MyClass
{
public void MyMethod() { }
}
static void Main(string[] args)
{
// Set a breakpoint here to see that mc = null.
// However, the compiler considers it "unassigned."
// and generates a compiler error if you try to
// use the variable.
// try Console.WriteLine(mc);
// it will return error CS0165: Use of unassigned local variable `mc'
MyClass mc;
// Now the variable can be used, but...
mc = null;
// ... a method call on a null object raises
// a run-time NullReferenceException.
// Uncomment the following line to see for yourself.
// mc.MyMethod();
// Now mc has a value.
mc = new MyClass();
// You can call its method.
mc.MyMethod();
// Set mc to null again. The object it referenced
// is no longer accessible and can now be garbage-collected.
mc = null;
}
答案 3 :(得分:-2)
他们是一样的。
事实上,如果您使用的是ReSharper,它会告诉您“= null”是多余的。
关于你的第二个问题。如果没有立即分配,我不会声明很多变量。
所以,如果你只是声明它
MyClass Instance2;
然后设置它。
MyClass = new Instance2;
Instance2.FirstProperty = "some string";
Instance2.SecondProperty = 1;
这可以全部合并为一个声明
var MyClass = new Instance2 { FirstProperty = "some string", SecondProperty = 1 };