通用列表为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
会指向您的错误。 (事实上,如果类型关系是正确的(即如果IEnumerable
是List
的超类型),则根本不需要转换。)
要解决您的问题,请使您的方法通用,以便它接受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
通过这种方式,您不必每次都转换为IEnumerable