我正在尝试编写一个通用的比较例程。但是,我班上的一些项目都在收藏中,我需要枚举进行比较。
有没有一种简单的方法,没有try / catch块来确定变量是否支持GetEnumerator()
答案 0 :(得分:4)
if (object is IEnumerable)
{
foreach(var value in (IEnumerable)object)
{
// ...
}
}
答案 1 :(得分:3)
将其投放到IEnumerable
:
var list = someVariable as IEnumerable;
if (list != null)
{
...
}
答案 2 :(得分:1)
GetEnumerator()
在IEnumerable
界面上定义,因此:
if (obj is IEnumerable)
{
...
}
答案 3 :(得分:1)
建议您检查对象是否为IEnumerable
的答案是合理的。绝大多数情况下,如果支持枚举,您的集合或对象将实现该接口。但这不是必需的。
对于foreach
中要枚举的内容,它实际上只需要公开一个GetEnumerator()
方法,该方法返回一个具有适当MoveNext()
和Current
实现的对象。考虑类似的事情:
class CustomCollection
{
public CustomEnumerator GetEnumerator()
{
return new CustomEnumerator();
}
}
class CustomEnumerator
{
public bool MoveNext()
{
return (++this.Current <= 10);
}
public int Current { get; private set; }
}
您可以将new CustomCollection()
置于循环中并获取值1..10。
一定要先检查界面。如果这就是你想支持的全部,那很好。如果你想加倍努力,你需要像编译器一样执行步骤,如检查适当的方法和返回类型。这是一个完全未经测试的草案的实现。
bool IsEnumerable(object obj)
{
if (obj is IEnumerable)
return true;
var info = obj.GetType().GetMethod("GetEnumerator");
if (info != null)
{
if (info.ReturnType != null)
{
var moveNextMethod = info.ReturnType.GetMethod("MoveNext");
if (moveNextMethod != null && moveNextMethod.ReturnType == typeof(bool))
{
var currentProperty = info.ReturnType.GetProperty("Current");
if (currentProperty != null)
return true;
}
}
}
return false;
}
LinqPad中的一些快速测试,但并非详尽无遗......
IsEnumerable(new CustomCollection()).Dump(); // true
IsEnumerable(1).Dump(); // false
IsEnumerable(new List<int>()).Dump(); // true
答案 4 :(得分:0)
检查它是否实现IEnumerable
。 IEnumerable<T>
派生自IEnumerable
,因此任何通用集合也都会实现IEnumerable
。
如果您有类型,则可以使用Type.IsAssignableFrom
如果您有实例,则可以使用is
/ as
运算符。
答案 5 :(得分:0)
IEnumerable
接口确定某些内容是否可枚举。