【问题标题】:Creating new object in loop在循环中创建新对象
【发布时间】:2016-02-22 14:28:54
【问题描述】:

我遇到了一点 C# 初学者问题。但我很确定这很容易解决。

foreach(var test in Tests)
{
     object testObj = new object();             
     //Do something with the object
}

如果我这样做,那么每次我通过循环时对象 testObj 都会被覆盖。是否可以不每次都覆盖它? 还是我必须使用数组?

编辑:好的,抱歉,我会尝试更具体: 我的目标是在这个循环中创建一些对象,然后为每个对象调用一个新线程。在那里我想对对象做一些事情,当我完成后我想释放它。

托马斯的Edit2:

foreach (var test in Tests)
{
     object testObj = new object();
     //Set some properties of the object
     Thread t = new Thread(() => manager(testObj));  
     t.Start();
}

public void manager(object testObj)
{
    //Do something with the object

    //Release it
}

【问题讨论】:

  • 你想创建不同名称的对象>
  • 是的,有可能,更具体点您面临的问题是什么?
  • 为什么需要在数组中创建对象?
  • 嗯,这取决于您在循环中尝试对这个对象做什么。
  • 有可能,但您能否更具体地说明您想要实现的目标

标签: c#


【解决方案1】:

您的问题有两个方面。

  1. 变量的寿命。局部变量只存在于定义它的块中。因此,您在 foreach 循环中定义了 testObj。因此,它只存在于块的一次迭代中,并在循环结束时结束。然后下一次迭代有一个新的 testObj。

这样

object testObj 

foreach(var test in Tests)
{
     testObj = new object();             
     //Do something with the object
}

可以解决这个问题,因为 testObj 是在循环之外定义的,因此无论迭代如何,都使用设置的值。

然后

  1. 你总是重新设置它。如果将变量设置为新值,则旧值将被新值覆盖。因此,如果您想保存您创建的每个 testObj(或为每个 testObj 使用 1 个变量,但通常只有完全的初学者才会这样做,那么您将不得不使用列表、数组等。为了完整起见,仅提及它并提及这是不应该做的事情,因为它会大大增加你的开销)。

所以你可以这样做:

List testObjList = new List();

foreach (var tests in Tests)
{
    testObjList.Add(new object());
    // Or alternatively  object testObj = new object();  testObjList.Add(testObj);
}

如果您将其直接添加到列表中(添加(新对象)),您可以使用testObjList[testObjList.Count - 1] 访问它(计数为 1,因为索引以 0 而不是 1 开头)。这与使用第二个变体的 testObj 时相同。

编辑: 要在线程中使用它们然后消除这些对象,您有 2 个选项。

1.) 该对象没有任何处置功能,那么您的原始代码在那里就可以了:

foreach(var test in Tests)
{
     object testObj = new object();             
     //Do something with the object
}

对象在块结束时丢失,但垃圾收集器决定何时真正删除它(有一些例外情况,例如图像,您可能需要执行特殊操作才能删除它们)。

如果您的对象属于具有它提供的处置功能的特定类(我们称其为 myobject 以免与普通对象混淆):

foreach(var test in Tests)
{
     using (myObject testObj = new myObject())
     {             
         //Do something with the object
     }
}

这意味着 myObject 对象仅存在于 using 块中,此外,当块结束时(即使通过异常), dispose 部分也会执行,这应确保垃圾收集器能够释放内存。

【讨论】:

  • 我不认为我的原始代码很好:(因为当我第二次通过循环时,第一个对象总是会丢失。
  • @xileb0 请参阅问题编号 1,即变量的生命周期。如果您在块内定义变量,则它仅在块执行中有效/存在一次,然后被重新创建(在循环块的情况下)。 msdn.microsoft.com/en-us/library/aa691170(v=vs.71).aspx 有点关于那个话题。
  • 好的,我明白你的意思,但是有没有办法在没有数组/列表的情况下解决这个问题?顺便说一句,我没有处置功能。
  • 从我的理解你想要做的是:在循环内创建一个新对象,然后在循环内使用它来运行一个线程,然后再创建下一个对象。是这样吗?如果是这样,那么您的原始代码就可以了,因为该变量仍然具有对其在内存中的原始地址的引用(在您将其作为参数提供的线程中)。因此它仍然存在于线程内部,而在原始循环中,具有该名称的变量被设置为一个新值(不影响线程内部的值)。
  • 请检查我的新编辑。这正是我想做的。所以我想拥有例如 20 个线程,并且每个线程都对特定对象执行某些操作。我想你理解错了。你以为我总是只想同时处理一个对象。
【解决方案2】:

在每次迭代中创建对象的新实例是完全可以的,因为该对象仅在一个生命周期的生命周期中需要。因此,您创建的每个线程都有自己的testObj 实例。如果你想在循环之后对对象做任何事情,你必须缓存它,无论是使用数组或列表的每个实例,还是使用 object testObject 在循环之前只使用最后一个实例,并在每次迭代中分配它 new .然而,这将导致引用 testObject 仅包含您在上次迭代中创建的最后一个实例。

object testObj;
foreach (var test in Tests)
{
     testObj = new object();  // creates a new instance every iteration
     //Set some properties of the object
     Thread t = new Thread(() => manager(testObj));  
     t.Start();
}

// do anything with the lastly created instance
DoSomething(testObject);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 2011-05-12
    • 1970-01-01
    相关资源
    最近更新 更多