【问题标题】:C# - How to create updatable enumerator?C# - 如何创建可更新的枚举器?
【发布时间】:2011-10-16 12:52:03
【问题描述】:

我对 C#(来自 PHP)有点新,我有点震惊,通过循环遍历列表我无法传递对该变量的引用,即以下代码无效:

foreach (ref string var in arr) {
    var = "new value";
}

我研究了一下I found a suggestion to create a "updatable enumerator",但我不知道我应该怎么做。我遵循了一个示例,并尝试为 IEnumerator.Current 方法和我的自定义枚举器 (PeopleEnum.Current) 添加 Current 设置器,但老实说,这是盲目的猜测并且不起作用。我将整个代码粘贴到 pastebin,因为在这里粘贴很长 - custom enumerator attempt。在这段代码中,尝试通过

访问当前元素
badClass baddie = new badClass(ref tmp.Current);

导致“属性或索引器可能无法作为 out 或 ref 参数传递”的预期错误

我最终的目标是这样的 - 遍历对象列表,为每个对象生成一个按钮,并为该按钮添加一个 onclick 事件,该事件将打开一个新表单,传递引用对于该对象,以便可以以该新形式编辑其内容。我做了所有这些,但是将对象作为参考而不是只读数据传递,这让我很生气。我将不胜感激任何答案,我可以阅读有关可更新枚举数或想法的链接。

【问题讨论】:

  • 对于很多枚举来说,能够替换当前项是没有意义的,所以不能作为通用机制。为什么不使用 for 循环?
  • 听起来您应该从对象的属性中设置用户控件的属性...这是您需要的吗?
  • 到底是什么问题正在扼杀你。我认为这可能是您没有详细说明的事情。
  • 你发现IEnumerator<>.Current只有一个getter,没有一个setter。这在很大程度上是设计使然,界面的简单性使其非常通用。尤其是赋予 Linq 权力。不是问题,只需使用 for(;;) 循环。

标签: c# object pass-by-reference enumerator


【解决方案1】:

首先——不想责怪你——我想说:如果你学习一门新语言,那就学习新语言!并且不要尝试使用 C# 开发 PHP。如果计算机语言都一样,我们就不会有那么多了。 ;-)

我不知道您的示例与您想要做的实际工作有何关系,但您可能应该首先了解事件、委托和 LINQ。可能会有这样的帮助:

foreach (Obj obj in yourBaseObjects) {
    Obj localObj = obj; // See Dans comment!!!
    Button button = new Button(); // however you create your buttons
    button.Click += {
         // do something with obj
         Console.WriteLine(localObj);
    }
}

是的,这在 C# 中有效,并且每个事件处理程序都将使用正确的对象。如果它不符合您的需求,您必须提供更多详细信息。

【讨论】:

  • 这里的闭包有问题。在您的示例中,所有代表都将引用列表中的 last 对象。您可以通过创建局部变量来保留引用的副本来解决该问题;这向编译器澄清了表达式应该关闭内部范围变量。
  • 谢谢,我会研究你的例子并提示我稍后需要阅读的内容,因为我现在需要出去几个小时。你们在这里给出的快速和有用的答案让我感到震惊,赞!
【解决方案2】:

为什么要使用 foreach 循环。使用 for 循环。我不知道确切的代码/语法,但类似:

int sizeOfArray=objectArray.size();
for(int i=0;i<sizeOfArray;i++)
{
    obj=objectArray[i];
    // use obj whatever you wany
}

【讨论】:

  • 是的,我昨晚尝试了一个“for”循环,但似乎我太累了,没有注意到我正在使用 2 个嵌套的 foreach-es 并且我正在尝试转换只有里面的一个。我目前正在尝试转换两者,我会尽快回答您(和其他人)的问题。感谢您朝着正确的方向推动(我希望):)
【解决方案3】:

听起来您不是在尝试传递对 Object 的引用(Object 已经是引用类型),而是对 Object 在数组中的位置的引用,对吗?由于它管理内存和引用的方式,后者在 .NET 中不能直接实现。您可以使用包装类完成类似的事情(没有错误处理,但这是基本思想):

public sealed class ListReference<T>
{
    private readonly IList<T> _list;
    private readonly int _index;

    public ListReference(IList<T> list, int index)
    {
        _list = list;
        _index = index;
    }

    public T Value
    {
        get { return _list[_index]; }
        set { _list[_index] = value; }
    }
}

您现在可以构造它并传递它,以及传递对数组的多个引用所带来的所有相关复杂性风险。如果可能的话,最好更改设计以避免这种情况,但有可能完成您所追求的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-03
    • 2011-01-31
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多