C# - 可以列出吗?无缝转换为列表或类似的?
我的控件中有一个 DataSource
,它始终是一个 List
,其中 T
必须从 IEntity
继承。
public class MyClass<T> where T : IEntity
{
public List<T> DataSource
{
get;
set;
}
}
现在,显然您不能将 List
转换为 List
执行以下操作:
List<IEntity> wontWork = (List<IEntity>)this.DataSource;
How can I get the DataSource as a List of IEntity
,同时仍然能够从 DataSource
添加和删除项目?即我可以执行以下操作,但从它返回的列表中删除不会从数据源中删除:
public List<TOut> GetDataSourceCopyAsUnderlyingType<TOut>()
{
if (this.DataSource == null)
{
return new List<TOut>();
}
else
{
// Get the list and the enumerator
IList list = (IList)this.DataSource;
IEnumerator enumerator = list.GetEnumerator();
// Build the target list
List<TOut> targetList = new List<TOut>();
int i = 0;
while (enumerator.MoveNext())
{
TOut entity = (TOut)list[i];
targetList.Add(entity);
i++;
}
return targetList;
}
}
基本上,我需要某种方法来执行以下操作:
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count; // Equals 5
int interfaceCount = interfaceList.Count; // Equals 5
interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count; // Equals 4
int interfaceCount = interfaceList.Count; // Equals 4
只是补充一下,我不介意这是否意味着我必须使用不同的类型而不是列表。
编辑:抱歉,忘了说我正在使用 .Net2.0,无法移动到 .Net 3.5。
I have a DataSource
in my control which is always a List<T>
where T
has to inherit from IEntity
.
public class MyClass<T> where T : IEntity
{
public List<T> DataSource
{
get;
set;
}
}
Now, obviously you can't cast a List<T>
to a List<IEntity>
doing the following:
List<IEntity> wontWork = (List<IEntity>)this.DataSource;
How can I get the DataSource as a List of IEntity
, whilst still being able to add and remove items from the DataSource
? I.e. I could do the following, but removing from the List it returns would not remove from the DataSource:
public List<TOut> GetDataSourceCopyAsUnderlyingType<TOut>()
{
if (this.DataSource == null)
{
return new List<TOut>();
}
else
{
// Get the list and the enumerator
IList list = (IList)this.DataSource;
IEnumerator enumerator = list.GetEnumerator();
// Build the target list
List<TOut> targetList = new List<TOut>();
int i = 0;
while (enumerator.MoveNext())
{
TOut entity = (TOut)list[i];
targetList.Add(entity);
i++;
}
return targetList;
}
}
Basically, I need some way of doing the following:
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count; // Equals 5
int interfaceCount = interfaceList.Count; // Equals 5
interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count; // Equals 4
int interfaceCount = interfaceList.Count; // Equals 4
And just to add, I don't mind if it means I've got to use a different type instead of a List.
EDIT: Sorry, forgot to say I'm using .Net2.0 and cannot move to .Net 3.5.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
DrPizza 所说的,但有更多代码:
如果参数不是
TIn
类型,则添加、插入和索引器集将会崩溃。What DrPizza said, but with more code:
Add, Insert and the indexer set will blow up if the argument is not of type
TIn
.好吧,这可能完全不是重点,但是,使用一点 Linq 怎么样?
这样你就可以轻松地转换objectList。
希望这有助于找到解决方案......
ok this might be completely beside the point but, how about using a little bit of Linq?
this way you can cast the objectList easily.
hope this helps to find the solution...
我也赞成 linq,但你可以这样做:
更短且更具表现力。
I'm in favor of linq too, but you can do it like:
Which is shorter and more expressive.
如果允许这样做,那将是一个非常糟糕的主意,这就是为什么不允许这样做。我可以将任何旧的 IEntity 添加到
List
中,如果该 IEntity 无法转换为 T,该列表将会爆炸。虽然所有 T 都是 IEntities,但并非所有 IEntities 都是 T。这适用于数组,因为数组有一个故意的子类型漏洞(就像在 Java 中一样)。集合没有子类型漏洞。
It would be a monumentally bad idea if this were allowed, which is why it isn't. I can add any old IEntity to a
List<IEntity>
which will blow up if that IEntity can't be cast to T. Whilst all Ts are IEntities, not all IEntities are Ts.This works with arrays because arrays have a deliberate subtyping hole (as they do in Java). Collections do not have a subtyping hole.
创建一个无缝转换的包装类。未经测试的示例:
对原始列表的操作也将反映在包装器中。要使用它,只需使用您的数据源构建它即可。
Create a wrapper class that seamlessly converts. Untested sample:
Manipulations of the original list will also be reflected in the wrapper. To use this, just construct it with your DataSource.