5

我经常在 C# 代码中看到以下约定:

some_type val;
val = something;

DataTable dt;
dt = some_function_returning_datatable();

或者

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

代替

some_type val = something;
DataTable dt = some_function_returning_datatable();

我最初认为这是您必须在作用域顶部声明所有局部变量时遗留下来的习惯。但我已经学会了不要这么快就抛弃资深开发者的习惯。

dt(在我的第三个代码部分中,当我们首先分配new函数然后从函数分配时不会浪费内存)

那么,是否有充分的理由在一行中声明,然后再分配?

4

5 回答 5

18

在我的第三个代码部分中,当我们首先将 dt 分配给 new 然后从函数分配时,它不会浪费内存

是的,确实会。只是相对较小 - 创建一个无用的DataTable对象 - 但仍然是浪费不清楚的。

那么,是否有充分的理由在一行中声明,然后再分配?

仅当您没有立即获得价值时。例如:

string x;
if (someCondition) {
    // Do some work
    x = someResult;
} else {
    // Do some other work
    x = someOtherResult;
}

通常可以使用条件运算符或将该代码提取到方法中来改进这一点。有时它不会那样工作。

对于以下简单情况:

Foo x = SomeInitializationWithNoUsefulSideEffects();
x = SomeUsefulValue();

或者

Foo x;
x = SomeUsefulValue();

绝对应该重构为

Foo x = SomeUsefulValue();

声明点确实产生影响的另一种有趣情况是在捕获的变量中,尽管通常不是预期的方式:

int x;
for (int i = 0; i < 10; i++) {
    x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

对比

for (int i = 0; i < 10; i++) {
    int x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

在第一个片段中,每个委托都将捕获相同的变量,因此他们都可以有效地看到从SomeFunction. 在第二个片段中,每个委托都将捕获一个单独的“实例” x

于 2012-05-08T10:38:19.500 回答
9

但我已经学会了不要这么快就抛弃资深开发者的习惯。

迅速解雇他们,不要担心或犹豫。用 C# 编写完全没有意义:

some_type val;
val = something;

代替:

some_type val = something;

或者:

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

代替:

DataTable dt = some_function_returning_datatable();

无论如何,如果您不在代码中解除它们,C# 编译器将在发出生成的 IL 时解除它们。

于 2012-05-08T10:37:03.997 回答
0

这是每个人自己的愿望。不存在性能问题。由于 CLR 会做出自己的声明,无论您如何声明,无论是一行还是两行。

我总是跟着

int i=5;

尽可能。

但可以肯定,因为当你声明 int i=5; 在单行中,CLR 必须创建一个新的整数实例。

于 2012-05-08T10:40:57.707 回答
0
SomeType someVar;
someVar = new(SomeType);

SomeType someVar = new(SomeType);

是等价物。可能是开发人员的习惯,可能是拆分是必要的,但已被重新考虑,但并不完全。

SomeType someVar = new(SomeType);
someVar = GetSomeTypeFromSomewhereElse();

充其量是低效的编码,因为第一个实例显然什么也没做,就会超出范围。取决于构造函数中的任何副作用的课程。如果有的话,那么在您的同行评审期间,我们将进行一次漫长而痛苦的交谈。:D

在那之后,正如其他人所说,这是因为someVar必须声明它,以便可以通过一些进一步的逻辑对其进行分配。

于 2012-05-08T11:02:14.727 回答
0

阅读代码时,了解哪些变量会在其范围内发生变化以及哪些不会发生变化是非常有用的。粗略表明这一点的一个有用约定是,如果变量的值在其范围内保持不变,则在其声明的同一行初始化一个变量,如果两者都在其声明之外的行上初始化它:

  1. 它的值将在其范围内重新分配,并且
  2. 这个事实不会立即显而易见

关于某事是否“立即显而易见”,有一些判断空间;一些符合条件的情况是:

  1. 将变量初始化为显然是常量值的东西(特别是如果它是类型的默认值)
  2. 在其定义的几行内重新分配值
  3. The names of the variable and the initialization expression suggest loop initialization (e.g. "var currentFoo = firstFoo;")

The longer the scope of a variable, the more likely I am to use separate initialization and declaration if the value will ever change.

于 2012-05-24T17:41:14.230 回答