C#,ArrayList 属性到列表字段

发布于 2024-09-15 15:00:21 字数 696 浏览 1 评论 0 原文

我有以下 Field:

private IList<Modulo> modulos;

和以下 Property:

    public virtual ArrayList XmlModulos
    {
        get
        {
            if (modulos == null) return new ArrayList();
            var aux = new ArrayList();
            foreach (Modulo m in modulos)
                aux.Add(m);
            return aux;
        }
        set
        {
            modulos = new List<Modulo>();
            foreach (object o in value)
                modulos.Add((Modulo)o);
        }

    }

get 工作完美,因为我有另一个用于不同目的的直接属性。但该集不起作用,因为当我使用此属性时,它不会更新任何内容。调试表明该属性是一个空的 ArrayList(计数为 0)并且该字段保持为 null。知道为什么这不起作用吗?任何帮助将不胜感激。

I have the following Field:

private IList<Modulo> modulos;

and the following Property:

    public virtual ArrayList XmlModulos
    {
        get
        {
            if (modulos == null) return new ArrayList();
            var aux = new ArrayList();
            foreach (Modulo m in modulos)
                aux.Add(m);
            return aux;
        }
        set
        {
            modulos = new List<Modulo>();
            foreach (object o in value)
                modulos.Add((Modulo)o);
        }

    }

The get works perfectly, as I have another direct property that is used for different purposes. But the set is not working, as when I use this property it doesn't update anything. The debug says that the Property is an empty ArrayList (count 0) and the field stays in null. Any Idea why this is not working? any help will be highly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天邊彩虹 2024-09-22 15:00:21

要理解这里发生的情况,您必须认识到 .NET 属性只是表示两个单独的方法的便捷方式,一个用于获取,另一个用于设置。

也就是说,它们基本上将这些操作映射

ArrayList m = obj.XmlModulos;

obj.XmlModulos = new ArrayList();

到实际上更类似于此的代码:

ArrayList m = obj.get_XmlModulos();

obj.set_XmlModulos(new ArrayList());

好的,考虑到这一点,让我们考虑一下您要做什么(这是基于对 Timwi 的回答):

obj.XmlModulos.Add(new Modulo());

真正所做的是:

obj.get_XmlModulos().Add(new Modulo());

考虑当您的 get 访问器创建一个新的 ArrayList 时,您永远无法将 Modulo 添加到您的以这种方式收集。唯一可以做到的方法是:

ArrayList m = obj.XmlModulos;

m.Add(new Modulo());

obj.XmlModulos = m;

但是,这是实现 getset 访问器的一种非常低效的方法。在每个 get 上创建一个新的 ArrayList 并用 modulos 的当前成员填充它的成本很高。枚举传递给 set 的任何值并将每个值复制到 modulos 也是如此。

如果说有什么不同的话,那就是这个类的设计是倒退的(实际上,大多数开发人员现在都会建议完全避开 ArrayList 类型;但如果您坚持的话,那是您的决定)。您在内部存储一个IList(提供类型安全),但在外部暴露一个ArrayList(它);这意味着有人可以轻松地尝试向您的列表中添加一些非Modulo 类型的随机对象,并且您会得到一个InvalidCastException。尝试执行此操作的代码实际上根本不应该编译;这就是泛型的全部意义。

好吧,我已经说够了。我有什么建议?只有一个属于此类的集合。确定您实际想要提供什么功能,并仅公开该功能。不要在两个集合之间来回进行这种昂贵的复制。

例如,如果您确实需要一个ArrayList,但您只需要启用客户端代码向其中添加和删除元素,然后按如下方式实现它:

private ArrayList modulos;

public void AddModulo(Modulo m)
{
    modulos.Add(m);
}

public bool RemoveModulo(Modulo m)
{
    return modulos.Remove(m);
}

这样,即使您正在使用内部非泛型 ArrayList(如果您有充分的理由这样做),您仍然可以通过仅允许客户端代码来获得 IList 的有效类型安全性添加和删​​除 Modulo 类型的项目。

这可能与对您实际有意义的解决方案有很大不同。至少希望它能够引导您走向正确的方向。

To understand what's going on here, you must realize that .NET properties are simply a convenient way to represent two separate methods, one for getting and another for setting.

That is, they basically map these operations:

ArrayList m = obj.XmlModulos;

obj.XmlModulos = new ArrayList();

to code that really more closely resembles this:

ArrayList m = obj.get_XmlModulos();

obj.set_XmlModulos(new ArrayList());

OK, so with this in mind, let's consider what you're trying to do (this is based on a comment to Timwi's answer):

obj.XmlModulos.Add(new Modulo());

What this is really doing is:

obj.get_XmlModulos().Add(new Modulo());

Considering your get accessor creates a new ArrayList, you're never going to be able to add a Modulo to your collection in this way. The only way you could do it would be this:

ArrayList m = obj.XmlModulos;

m.Add(new Modulo());

obj.XmlModulos = m;

HOWEVER, this is a very inefficient way to implement your get and set accessors. Creating a new ArrayList on every get and populating it with the current members of modulos is costly. So is enumerating over any value passed to set and copying each to modulos.

If anything, this class design is backwards (really, most developers would advise steering clear of the ArrayList type altogether these days; but if you insist, that's your call). You are storing an IList<Modulo> (which provides type safety) internally but exposing an ArrayList (which does not) externally; what this means is that someone could easily try to add some random object of non-Modulo type to your list and you would get an InvalidCastException. Code that tries to do this really ought not to compile at all; that's the whole point of generics.

OK, I've said enough. What do I suggest? Have just one collection belonging to this class. Decide what functionality you actually want to provide, and expose just that functionality. Don't do this expensive copying back and forth between two collections.

For example, if you truly need an ArrayList, but you only need to enable client code to add and remove elements to/from it, then implement it like this:

private ArrayList modulos;

public void AddModulo(Modulo m)
{
    modulos.Add(m);
}

public bool RemoveModulo(Modulo m)
{
    return modulos.Remove(m);
}

This way, even though you're using a non-generic ArrayList internally (if you have good reasons for this), you're still getting the effective type safety of an IList<T> by only allowing client code to add and remove items of the Modulo type.

This could be very different from the solution that actually makes sense for you. Let it hopefully steer you in the right direction, at least.

梦幻的心爱 2024-09-22 15:00:21

我无法重现您的问题;我复制了您的代码,然后执行了这一行:

XmlModulos = new ArrayList { new Modulo() };

此后,调试器和 Console.WriteLine 都报告 modulos.CountXmlModulos.Count1

因此,错误在于您未向我们展示的其他一些代码。

I cannot reproduce your issue; I copied your code and then executed this line:

XmlModulos = new ArrayList { new Modulo() };

After this, both the debugger and Console.WriteLine report both modulos.Count and XmlModulos.Count as 1.

Therefore, the error lies in some other code that you haven’t shown us.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文