给类的实例赋值null和只声明有什么区别



我试图理解将null赋值给类的实例和仅声明该类之间是否有任何区别。

举个例子,我有一个类:

public class MyClass
{
public string FirstProperty { get; set; }
public int SecondProperty { get; set; }
}

我声明类的两个实例:

MyClass Instance1 = null;
MyClass Instance2;  // just declaration

Instance1Instance2之间有什么区别吗

如果是,它安全吗?使用"仅delcaration"样式是一个好习惯吗(就像上面例子中的Instance2一样)?

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

您没有创建任何实例。如果实例已经创建,您将创建两个放置实例的位置。你明确说的第一个没有实例,第二个就是没有实例。

Instance1Instance2之间有什么区别吗?

这取决于你在哪里做的。

如果该代码在classstruct中,那么您已经创建了两个字段,除非构造函数执行其他操作,否则这两个字段最初都将设置为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.

是的,只使用声明的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,那么这样的错误就不会那么明显,而且可能会导致错误。

因此,在像裸声明这样的情况下更好。

但也就是说,在可能的情况下,总是最好避免复杂的逻辑,所以这种错综复杂的链条应该很少见。在其他情况下,在同一点声明和赋值的风格意味着在这两者之间没有差距,错误可能会出现

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

对于第一个,您显式分配null。到了第二天,你什么都不分配。因此,它包含默认值,对于引用类型,该值为null1

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

MyClass Instance1 = null;
MyClass Instance2;
Console.WriteLine(Instance1); // fine
Console.WriteLine(Instance2); // raises error CS0165

1正如stuartd和Kyle所评论的,编译器可能根本无法初始化局部变量,这解释了错误。无论是null还是创建的MyClass实例,在分配变量之前,都不能依赖具有任何特定值的变量。字段和属性将初始化为类型的默认值(null表示引用类型)。

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;
}

它们是相同的。

事实上,如果您使用ReSharper,它会告诉您"=null"是多余的。

至于你的第二个问题。我不会在没有立即赋值的情况下声明很多变量。

所以如果你只是像一样声明

MyClass Instance2;

然后设置。

MyClass = new Instance2;
Instance2.FirstProperty = "some string";
Instance2.SecondProperty = 1;

所有这些都可以组合在一个语句中

var MyClass = new Instance2 { FirstProperty = "some string", SecondProperty = 1 };

相关内容

  • 没有找到相关文章

最新更新