英文:
Convert from System.Collections.Generic.IList<object> to System.Collections.IList
问题
我已经实现了以下类:
class LazyList<T> : IList<T>
{
public LazyList(IEnumerable<T> enumerable) { }
}
我需要将这个类与非泛型的旧版 System.Collections
一起使用。我已经通过使用 IEnumerable.Cast<object>()
解决了一半的问题,如此处描述:https://stackoverflow.com/a/776407/2109230/。
然而,我需要将 LazyList<T>
强制转换为非泛型的 IList
以完成重构过程。我应该如何实现这个?
更新 1:
LazyList 基本上帮助我重构一个在迭代 IDataReader 后返回 IList 的方法。我使用从这个方法返回的数据来通过 WebSocket 发送一些更新。重点是不断地发送数据,而不是在处理整个 IDataReader 后才发送。我已经使用 yield return 返回了一个懒惰的 IEnumerable,但其他方法要求重构后的方法返回 IList。因此,我想到了 LazyList 的主意。
实际上有两种方法,一种返回 IList<T>
,我已经成功地重构了它,另一种返回 IList
。我想知道是否有一种更简单的方法来重构返回 IList 的版本,而不必实现非泛型的 LazyList。但是,我已经这样做了,而且情况并不那么糟糕。
英文:
I have implemented the following class:
class LazyList<T> : IList<T>
{
public LazyList(IEnumerable<T> enumerable) { }
}
I need to use this class with non-generic legacy System.Collections
. I have solved half of the problem by using IEnumerable.Cast<object>()
as described here <https://stackoverflow.com/a/776407/2109230/>.
However, I need to cast LazyList<T>
to non-generic IList
to complete the refactor process. How can I achieve this?
UPDATE 1:
LazyList basically helps me refactor a method that returns IList after iterating an IDataReader. I use data returned from this method to send some updates over WebSocket. The point is to send data constantly, not after processing the entire IDataReader. I have used yield return to return a lazy IEnumerable, but other methods require the refactored method to return IList. So, I came up with the idea of LazyList.
There are actually two methods, one returning IList<T>
, which I have refactored successfully, and another returning IList
. I wanted to see if there is a simpler way to refactor the version returning IList, without implementing non-generic LazyList. However, I did that and it wasn't that bad.
答案1
得分: 1
你应该按照List<T>
所做的方式进行操作 - 实现两个接口并使用显式接口实现来消除一些重复(请参阅源代码)并限制暴露的合同。以下是一个起始示例:
class LazyList<T> : IList<T>, IList
{
public LazyList(IEnumerable<T> enumerable) { }
public void Add(T item) => throw new NotImplementedException();
public int Count { get; }
public int Add(object? item)
{
Add((T)item!); // 调用泛型实现
return Count - 1;
}
int IList.IndexOf(object? item)
{
if (IsCompatibleObject(item))
{
return IndexOf((T)item!); // 调用泛型实现
}
return -1;
}
public int IndexOf(T item) => throw a NotImplementedException();
private static bool IsCompatibleObject(object? value) => (value is T) || (value == null && default(T) == null);
// ...
}
英文:
You should follow the pattern the List<T>
does - implement both interfaces and use explicit interface implementations to remove some duplication (see the source code) and limit the exposed contract. Something to get you started:
class LazyList<T> : IList<T>, IList
{
public LazyList(IEnumerable<T> enumerable) { }
public void Add(T item) => throw new NotImplementedException();
public int Count { get; }
public int Add(object? item)
{
Add((T)item!); // call to the generic implementation
return Count - 1;
}
int IList.IndexOf(object? item)
{
if (IsCompatibleObject(item))
{
return IndexOf((T)item!); // call to generic
}
return -1;
}
public int IndexOf(T item) => throw new NotImplementedException();
private static bool IsCompatibleObject(object? value) => (value is T) || (value == null && default(T) == null);
// ...
}
答案2
得分: 1
我同意 @Panagiotis Kanavos 的说法:“IList
不是 IList<object>
,它是一个完全不同的接口”。此外,如果使用非泛型 IEnumerable
创建的 LazyList<T>[index]
访问,如果 T 被初始化为除 object 以外的任何类型,将会引发转换错误。
最后,我另外创建了一个实现了 IList
接口的类,使用原始的 LazyList<T>
,以避免将 object 强制转换为 T:
public class LazyList : IList
{
LazyList<object> _lazyList;
public LazyList(IEnumerable enumerable)
{
_lazyList = new LazyList<object>(enumerable.Cast<object>());
}
}
虽然我复制了方法,但似乎没有其他方法。
英文:
I agree with @Panagiotis Kanavos stating that: "An IList
isn't an IList<object>
, it's a completely different interface". In addition, accessing LazyList<T>[index]
created from a non-generic IEnumerable
, will throw a conversion error if T is initialized with anything else than object.
I ended up with another class implementing IList
using the original LazyList<T>
, to avoid casting object to T:
public class LazyList : IList
{
LazyList<object> _lazyList;
public LazyList(IEnumerable enumerable)
{
_lazyList = new LazyList<object>(enumerable.Cast<object>());
}
}
I did duplicate the methods, but it seems there is no other way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论