在循环C#中创建对象

时间:2010-02-23 20:16:23

标签: c#

对下面的代码感到好奇。

for (int i=0; i<9; i++)
{
   ClassA objectA = new ClassA();
}

ClassA objectA;
for (int i=0; i<9; i++)
{
    objectA = new ClassA();
}

这两个代码有什么不同吗? 根据我的知识,每次都会创建不同的实例,所以实例的数量会相同。任何想法?

9 个答案:

答案 0 :(得分:25)

除了范围外(即变量是否存在于循环外),通常没有区别,因为.NET变量实际上(在IL中)所有在 start 无论如何,这个方法。但是,有一个例外:如果您捕获变量(进入匿名方法/ lambda),那么它的行为会有所不同 - capture 的构造是为了尊重C#声明。所以:

List<Action> actions = new List<Action>();
ClassA objectA;
for (int i=0;i<9;i++)
{
    objectA= new ClassA();
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });        
}
foreach(Action action in actions) action();

List<Action> actions = new List<Action>();
for (int i=0;i<9;i++)
{
    ClassA  objectA= new ClassA();
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });        
}
foreach(Action action in actions) action();

将做不同的事情(第一次打印相同的基于地址的哈希码9次;第二次打印9 不同的基于地址的哈希码,表明在第二个循环中,我们捕获了9个不同的变量,而不是单个变量。)

在这两种情况下都创建了9个ClassA个对象 - 只是在第一种情况下我们再也看不到其中的8个。

答案 1 :(得分:13)

唯一的区别是,在第二个示例中,在循环后仍然可以访问最后创建的实例

答案 2 :(得分:2)

实际上,由于您从未保存对您创建的对象的引用,因此每次覆盖objectA时,您都将删除前一个示例。

然而,在以下情况下:

for (int i=0;i<9;i++)
{
   ClassA objectA = new ClassA();
}

objectA不存在于循环范围之外,并且您创建的所有对象最终将被垃圾收集器删除。在循环之外引用objectA将是语法错误。

相反,在以下情况下:

ClassA objectA;
for (int i=0;i<9;i++)
{
    objectA= new ClassA();
}

objectA是循环之外的有效标识符,创建的ClassA的最终实例将在循环完成后保留。

答案 3 :(得分:2)

实例数不会根据代码递增。两个循环只是重新初始化一个相同的变量,唯一的区别是第一个循环上的实例变量在完成循环时不可访问,这与第二个循环不同,其中变量在循环外声明。

答案 4 :(得分:1)

在第一个代码段中,无法在循环外访问objectA。因此,如果你写了:

for (int i=0;i<9;i++) 
{ 
    ClassA objectA = new ClassA(); 
}
// This will not compile.
objectA.DoSomething();

您将收到编译错误。但是,如果您将代码编写为:

ClassA objectA; 
for (int i=0;i<9;i++) 
{ 
    objectA= new ClassA(); 
}
// This will compile.
objectA.DoSomething();

第二个代码片段将编译(假设ClassA有一个名为DoSomething()的方法)。

答案 5 :(得分:0)

最大的区别在于,如果在循环内创建一个捕获objectA的闭包,那么闭包会转义循环。换句话说,如果objectA在循环外部以某种方式可见,那么第一个实例在循环结束后将有9个不同的值,而第二个实例在循环结束后将只有最后一个值。

例如,

for (int i = 0; i < 9; i++)
{
    ClassA objectA = new ClassA();
    someFunc(() => objectA);
}

可能与

有不同的可见结果
ClassA objectA;
for (int i = 0; i < 9; i++)
{
    objectA = new ClassA();
    someFunc(() => objectA);
}

答案 6 :(得分:0)

两者之间的区别在于,在for循环完成后,最后一次迭代(i = 8)的ClassA实例将可用于函数的其余部分,而在第一个版本中,它不会是

答案 7 :(得分:0)

唯一的区别是objectA将指向第二个循环后的ClassA示例。 在这两种情况下,都会创建9个对象,但在第一种情况下,所有这些对象都将被销毁,而在第二种情况下 - 最后一个对象将不会被销毁。

答案 8 :(得分:0)

prakash,只是为了正确性/完整性:在循环结束后无法访问变量是不正确的。我们通常假设创建的对象非常简单,可能不是这种情况。例如,您可以将对象添加到构造函数内的全局列表中,因此在循环结束后仍然可以访问所有对象

相关的区别是kbrinley指出的区别,因为你不能在第一个例子的范围之外使用变量(它是一个对象引用)(在{和}之间)。因为在第二个上你将变量声明在循环之外,你仍然可以使用变量。

正如Marc Gravell所说,两者的IL生成是相同的,因此在性能,内存占用等方面应该没有区别,用于循环。[1]


1:由于在第二个示例中肯定保留对最后一个变量的引用,因此垃圾收集器将无法释放其空间。因此,在循环结束后,会有细微的差异。