我经常在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();
我最初认为这是你必须在范围顶部声明所有局部变量的日子遗留下来的习惯。但我已经学会了不要那么快地解雇资深开发者的习惯。
(在我的第3段代码中,当我们首先使用dt
然后从函数分配new
时,不会浪费内存。
那么,有一个很好的理由在一行中声明,然后分配吗?
答案 0 :(得分:18)
在我的第3段代码中,当我们首先使用new然后从函数分配dt时,它不会浪费内存
是的,确实如此。只是相对较小 - 创建一个无用的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));
}
VS
for (int i = 0; i < 10; i++) {
int x = SomeFunction();
actions.Add(() => Console.WriteLine(x));
}
在第一个代码段中,每个代理都会捕获相同的变量,这样他们就能有效地看到SomeFunction
返回的最后一个值。在第二个代码段中,每个代理都将捕获x
的单独的“实例”。
答案 1 :(得分: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时将它们解雇。
答案 2 :(得分:0)
每个人都有自己的愿望。没有性能问题。因为CLR会声明你自己的声明,无论是在一行还是两行。
我总是跟着
int i=5;
尽可能。
但请确保,因为当你声明int i = 5时;在单行中,CLR必须创建一个新的整数实例。
答案 3 :(得分:0)
SomeType someVar;
someVar = new(SomeType);
和
SomeType someVar = new(SomeType);
是等价物。可能是一个开发人员的习惯,可能是分裂是必要的,但已被重新考虑,但不完全。
SomeType someVar = new(SomeType);
someVar = GetSomeTypeFromSomewhereElse();
最好是效率低下的编码,因为第一个实例将超出范围,显然没有做任何事情。课程取决于构造函数中的任何副作用。如果有一些,那么我们将在您的同行评审期间进行长时间的痛苦聊天。 :d
之后,正如其他人所说的那样,因为必须声明someVar
,所以可以通过其他逻辑分配它。
答案 4 :(得分:0)
在阅读代码时,了解哪些变量会在其范围内发生变化以及哪些变量不会发生变化非常有用。粗略地表明这一点的一个有用的约定是,如果一个变量在其整个范围内保持不变,则在与该声明相同的行上初始化一个变量,并在与它的声明分开的行上初始化它,如果两者都是:
关于某些事情是否“立即显而易见”,还有一些判断空间;一些符合条件的情况是:
变量的范围越长,如果值发生变化,我就越有可能使用单独的初始化和声明。