C#,ArrayList 属性到列表字段
我有以下 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要理解这里发生的情况,您必须认识到 .NET 属性只是表示两个单独的方法的便捷方式,一个用于获取,另一个用于设置。
也就是说,它们基本上将这些操作映射
到实际上更类似于此的代码:
好的,考虑到这一点,让我们考虑一下您要做什么(这是基于对 Timwi 的回答):
这真正所做的是:
考虑当您的
get
访问器创建一个新的ArrayList
时,您永远无法将Modulo
添加到您的以这种方式收集。唯一可以做到的方法是:但是,这是实现
get
和set
访问器的一种非常低效的方法。在每个get
上创建一个新的ArrayList
并用modulos
的当前成员填充它的成本很高。枚举传递给set
的任何值并将每个值复制到modulos
也是如此。如果说有什么不同的话,那就是这个类的设计是倒退的(实际上,大多数开发人员现在都会建议完全避开 ArrayList 类型;但如果您坚持的话,那是您的决定)。您在内部存储一个
IList
(提供类型安全),但在外部暴露一个ArrayList
(它不);这意味着有人可以轻松地尝试向您的列表中添加一些非Modulo
类型的随机对象,并且您会得到一个InvalidCastException
。尝试执行此操作的代码实际上根本不应该编译;这就是泛型的全部意义。好吧,我已经说够了。我有什么建议?只有一个属于此类的集合。确定您实际想要提供什么功能,并仅公开该功能。不要在两个集合之间来回进行这种昂贵的复制。
例如,如果您确实需要一个
ArrayList
,但您只需要启用客户端代码向其中添加和删除元素,然后按如下方式实现它:这样,即使您正在使用内部非泛型
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:
to code that really more closely resembles this:
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):
What this is really doing is:
Considering your
get
accessor creates a newArrayList
, you're never going to be able to add aModulo
to your collection in this way. The only way you could do it would be this:HOWEVER, this is a very inefficient way to implement your
get
andset
accessors. Creating a newArrayList
on everyget
and populating it with the current members ofmodulos
is costly. So is enumerating over any value passed toset
and copying each tomodulos
.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 anIList<Modulo>
(which provides type safety) internally but exposing anArrayList
(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 anInvalidCastException
. 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: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 anIList<T>
by only allowing client code to add and remove items of theModulo
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.
我无法重现您的问题;我复制了您的代码,然后执行了这一行:
此后,调试器和
Console.WriteLine
都报告modulos.Count
和XmlModulos.Count
如1
。因此,错误在于您未向我们展示的其他一些代码。
I cannot reproduce your issue; I copied your code and then executed this line:
After this, both the debugger and
Console.WriteLine
report bothmodulos.Count
andXmlModulos.Count
as1
.Therefore, the error lies in some other code that you haven’t shown us.