C#变量初始化、性能和良好实践
本文关键字:性能 变量 初始化 | 更新日期: 2023-09-27 18:22:22
如果这个线程被认为是主观的,我很抱歉,但我的问题更多地是技术方面的。
我在Framework.Net 4.0中使用C#。我花了几年时间玩C++,我接受的教育是,未初始化的变量会让我大吃一惊。
今天,每当我在C#代码片段中看到一个未初始化的变量时,我都会有点发抖,我真的无法决定是否应该初始化它们。
我读过很多文章,人们说,有些初始化了,有些没有(成员与本地),我读过一些文章,人们认为在C#中初始化vars会给性能带来麻烦。。。
在我当前的应用程序中,我希望有良好的性能,但首先,我需要避免因为变量未初始化而出现愚蠢的错误。
这方面的最佳实践是什么?
编辑:
public MyClass
{
private int foo; // Is it initialized ? Do I have to ?
public void MyMethod()
{
int bar; // Is it initialized ? Do I have to ?
...
}
} // Is it a good practice to initialize every vars all the time or not ?
// Will I get troubles by not initializing those ?
// If I do initialize them, will I get performance slowdown ?
在C#中,您不会像在C/C++中那样遇到未初始化变量具有随机值的问题。
某些变量(例如字段/静态)保证初始化为其默认值(通常为null/0),并且编译器在所有情况下都会给您一个错误,在这些情况下,默认值没有得到保证,并且您在使用前没有手动初始化变量。
换句话说,如果您不确定,请相信编译器会告诉您。
编辑:反之亦然,如果您手动将方法中的局部变量初始化为默认值,并且编译器可以看到您在更改它之前从未使用过它,它将为您删除初始化,因此除非您实际使用该值,否则不会产生开销。
我想知道,如果在C#中,所有变量都是自动的初始化,或者在某些情况下没有
当您声明引用类型变量(如SomeClass
的实例)时,它的默认值将是null
。一旦您使用新的为变量分配了一些内存,您的变量就会被初始化
SomeClass someClass; //not initialized, it's value is null
someClass = new SomeClass(); //initialized
另一方面,当您声明值类型时,它们会被初始化。例如
int bar; //initialized with value 0
是否始终初始化每个vars是一种好的做法?
好吧,这取决于场景。例如,当您声明布尔时,它的默认值是false
。但为了读者的理解,最好明确地做bool myBool = false
。另一方面,如果必须将变量作为out
传递给某个方法,初始化变量是没有用的,因为它是方法的责任。这实际上取决于你的情景和你喜欢遵循的实践。
如果不初始化这些,我会遇到麻烦吗?
如果您对默认值(未初始化的值)很满意,那么您就不会遇到麻烦。但是,如果您的代码需要一些初始化值,而您的变量没有初始化,那么您可能会遇到麻烦。
如果我真的初始化了它们,我的性能会降低吗?
没有。如果你的应用程序的性能真的很慢,你应该使用一些探查器来找出导致性能慢的原因。初始化变量不太可能导致性能问题
在C#中初始化或不初始化变量取决于您想要实现的目标,这两个选项在不同的情况下都有效。
例如,一个类公开了一些属性,并且您希望这些属性具有默认值:
public class X
{
private object _propertyName;
public object PropertyName
{
get { return _propertyName; }
set
{
_propertyName = value;
doSomething();
}
}
}
在这个类中,如果您试图在设置属性值之前读取该属性的值,那么保持_propertyName
未初始化可能会使您暴露于NullReferenceException
,因此将其初始化为合适的默认值是很好的做法。
但是,有时您希望为用户提供传入null
的选项,在这种情况下,初始化变量可能会覆盖此合法输入。
public void doSomethingToObjectInCollection(object key, List<object> haystack)
{
// First find it in the collection
object foundValue;
for( int i = 0; i < haystack.Count; i++ )
{
if( haystack[i].KeyField == key )
foundValue = key;
}
if( foundValue != null )
{
// Do something here if there was a foundValue
}
}
在本例中,将foundValue初始化为默认值将导致不正确的行为。当然,如果很难查看,可以显式地将其初始化为null
,但这不会改变代码的行为(与C++不同)。
至于性能方面的考虑,不幸的是,没有"是的,这很糟糕"或"不是,这没关系"的答案。在大多数应用程序中,这可能无关紧要,但如果您有严格的性能要求,那么决定要做什么需要特定于上下文的理解,即在初始化变量时到底发生了什么。
值类型将在分配为零时初始化,但这几乎不是一个昂贵的操作,因此可能不会让您过于担心。
引用类型是指在使用值之前初始化值可能会导致性能下降的地方。例如:
public class TheClass
{
MyType x = new MyType();
public TheClass()
{
x = new MyType(/*some arguments*/);
}
}
这将导致对x进行两次分配,第一次使用默认构造函数,第二次在构造函数内使用新值。这是因为类级变量是在构造函数之前初始化的。