通用列表为IEnumerable

我正在尝试将List转换为IEnumerable,因此我可以validation不同的列表不为null或为空:

假设myList是List 。 然后在我想要的来电代码中:

Validator.VerifyNotNullOrEmpty(myList as IEnumerable, @"myList", @"ClassName.MethodName"); 

有价值的代码是:

  public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable, string theIEnumerableName, string theVerifyingPosition) { string errMsg = theVerifyingPosition + " " + theIEnumerableName; if (theIEnumerable == null) { errMsg += @" is null"; Debug.Assert(false); throw new ApplicationException(errMsg); } else if (theIEnumerable.Count() == 0) { errMsg += @" is empty"; Debug.Assert(false); throw new ApplicationException(errMsg); } } 

但是,这不起作用。 它编译,但是无数是空的! 为什么?

IEnumerable不是IEnumerable的超类型,因此它也不是List的超类型。 请参阅问题2575363以简要概述为什么会出现这种情况(它是关于Java的,但概念是相同的)。 顺便说一下,这个问题已经在C#4.0中得到了解决,它支持协变generics 。

您没有找到此错误的原因是因为您使用x as T ,您应该使用正常转换( (T)x ),请参阅问题2139798 。 由此产生的InvalidCastException会指向您的错误。 (事实上​​,如果类型关系是正确的(即如果IEnumerableList的超类型),则根本不需要转换。)

要解决您的问题,请使您的方法通用,以便它接受IEnumerable而不是IEnumerable ,并完全跳过转换。

  public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable, string theIEnumerableName, string theVerifyingPosition) { ... } 

List实现IEnumerable,所以你不需要强制转换它们,你只需要让它接受一个generics参数,就像这样:

  public static void VerifyNotNullOrEmpty(this IEnumerable theIEnumerable, string theIEnumerableName, string theVerifyingPosition) { string errMsg = theVerifyingPosition + " " + theIEnumerableName; if (theIEnumerable == null) { errMsg += @" is null"; Debug.Assert(false); throw new ApplicationException(errMsg); } else if (theIEnumerable.Count() == 0) { errMsg += @" is empty"; Debug.Assert(false); throw new ApplicationException(errMsg); } } 

你应该只能用它来调用它:

 var myList = new List { "Test1", "Test2" }; myList.VerifyNotNullOrEmpty("myList", "My position"); 

您还可以稍微改进实施:

  public static void VerifyNotNullOrEmpty(this IEnumerable items, string name, string verifyingPosition) { if (items== null) { Debug.Assert(false); throw new NullReferenceException(string.Format("{0} {1} is null.", verifyingPosition, name)); } else if ( !items.Any() ) { Debug.Assert(false); // you probably want to use a better (custom?) exception than this - EmptyEnumerableException or similar? throw new ApplicationException(string.Format("{0} {1} is empty.", verifyingPosition, name)); } } 

假设您至少定位到框架3.0:

使用扩展名转换为通用IEnumerable

 var myEnumerable = myList.Cast(); 

编辑:无论如何我建议你改变你的方法来获得一个纯IEnumerable像:

 public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable, string theIEnumerableName, string theVerifyingPosition) 

在方法内部检查是否为空,使用foreach或theIEnumerable.Cast().Count()

通过这种方式,您不必每次都转换为IEnumerable