C# 变量初始化:直接还是在构造函数中?
可能重复:C# 变量初始化:直接还是在构造函数中?,c#,initialization,C#,Initialization,可能重复: 大多数时候,我看到了初始化变量的方法,就像这样 public class Test { private int myIntToInitalize; public Test() { myIntToInitalize = 10; } } 在我看来,这是初始化变量最常用的方法。书籍、博客以及.NET内部实现中的大部分代码都与我的示例相同 最近,我看到人们直接进行初始化,因此没有在构造函数中设置值 public class Test {
大多数时候,我看到了初始化变量的方法,就像这样
public class Test
{
private int myIntToInitalize;
public Test()
{
myIntToInitalize = 10;
}
}
在我看来,这是初始化变量最常用的方法。书籍、博客以及.NET内部实现中的大部分代码都与我的示例相同
最近,我看到人们直接进行初始化,因此没有在构造函数中设置值
public class Test
{
private int myIntToInitalize = 10;
}
从这个角度来看,初始化和声明变量与在构造函数中初始化变量没有区别
public class Test
{
private int myIntToInitalize = 10;
}
除了最佳实践和代码行长度之外,直接初始化变量的好处在哪里?是否存在细微的差异?我不知道有任何细微的差异。我通常喜欢将所有初始化都放在构造函数中,因为我认为这会使代码更具可读性。但这更多的是一种风格选择和个人偏好。我还没听说过有什么技术上的理由来证明这一点。我怀疑这会对性能产生任何影响
静态常数和最终常数是不同的。我在线初始化这些变量。构造实例时,在声明时初始化的任何变量都将在构造函数运行之前初始化。如果您没有访问这些变量或在构造函数本身中使用它们的值,那么这两种方法之间就没有功能上的差异。在某些情况下,有一个潜在的显著差异 实例初始值设定项在执行基类构造函数之前执行。因此,如果基类构造函数调用派生类中重写的任何虚拟方法,该方法将看到差异。然而,通常这不应该是一个明显的区别,因为在构造函数中调用虚拟方法几乎总是一个坏主意 为了清楚起见,如果您在声明点初始化变量,那么很明显该值不依赖于任何构造函数参数。另一方面,在我看来,将所有初始化放在一起也有助于可读性。我会尽可能确保,如果你有多个构造函数,它们都会委托给一个“主”构造函数来完成所有“真正”的初始化,这意味着你只能将这些赋值放在一个地方 演示差异的示例代码:
using System;
class Base
{
public Base()
{
Console.WriteLine(ToString());
}
}
class Derived : Base
{
private int x = 5;
private int y;
public Derived()
{
y = 5;
}
public override string ToString()
{
return string.Format("x={0}, y={1}", x, y);
}
}
class Test
{
static void Main()
{
// Prints x=5, y=0
new Derived();
}
}
举个简单的例子,这只是风格的问题 当涉及到继承时,会有细微的差别。例如字段初始值设定项,执行顺序为派生类字段初始值设定项、基类字段初始值设定项、基类构造函数、派生类构造函数 以这个样本为例:
public class Program
{
public static void Main(string[] args)
{
new Derived();
}
}
public class Base
{
private int x = BaseInitializer();
public Base()
{
Console.WriteLine("Base ctor");
}
private static int BaseInitializer()
{
Console.WriteLine("BaseInitializer");
return 0;
}
}
public class Derived : Base
{
private int x = DerivedInitializer();
public Derived() : base()
{
Console.WriteLine("Derived ctor");
}
private static int DerivedInitializer()
{
Console.WriteLine("DerivedInitializer");
return 0;
}
}
它打印:
- 衍生初始值设定项
- 碱基初始值设定项
- 基极导体
- 导出的向量
但是当你调用需要1个参数的构造函数时,类Test2上就没有了。假设我们在发布和优化版本下编译以下代码
namespace ConsoleApplication4
{
public class Test1
{
private int myIntToInitalize;
public Test1()
{
myIntToInitalize = 10;
}
}
public class Test2
{
private int myIntToInitalize = 10;
}
static class Program
{
private static void Main()
{
}
}
}
Test1类的IL指令
.class public auto ansi beforefieldinit Test1
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ldarg.0
L_0007: ldc.i4.s 10
L_0009: stfld int32 ConsoleApplication4.Test1::myIntToInitalize
L_000e: ret
}
.field private int32 myIntToInitalize
}
Test2类的IL指令
.class public auto ansi beforefieldinit Test2
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.s 10
L_0003: stfld int32 ConsoleApplication4.Test2::myIntToInitalize
L_0008: ldarg.0
L_0009: call instance void [mscorlib]System.Object::.ctor()
L_000e: ret
}
.field private int32 myIntToInitalize
}
很明显,这两个类都有相同数量的IL指令,唯一的区别是
在类Test1中调用::ctor()之前初始化变量;
和
在类Test2中调用::ctor()后初始化变量
注意:从性能角度看,这两个类的性能都是相同的,因为它们有相同数量和类型的IL指令,只是IL指令的执行顺序不同可能重复,我认为使用构造函数是完全多余的。为什么要把事情复杂化,编写更多冗余代码?我通常只在无法直接进行初始化时才在构造函数中进行初始化,例如当必须将一些参数传递给变量初始化所依赖的构造函数时。否则:private int myIntToInitalize=10;不要把事情搞得太复杂,让它们尽可能简单。代码越少越好!!!它们甚至在基类构造函数运行之前就已经运行了。这在处理虚拟方法时变得更加重要。从构造函数调用虚拟方法不是一个好的做法,但是如果您从基构造函数调用aVirtualMethod,并且派生的类会覆盖它,那么您会发现在执行aVirtualMethod之前会“执行”任何变量初始值设定项,但派生的构造函数还不会执行。其他信息: