我正在尝试将List转换为IEnumerable,因此我可以验证不同的列表不为null或为空:
假设myList是List< T> 。然后在我想要的来电代码中:
Validator.VerifyNotNullOrEmpty(myList as IEnumerable<object>,
@"myList",
@"ClassName.MethodName");
有价值的代码是:
public static void VerifyNotNullOrEmpty(IEnumerable<object> 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);
}
}
然而,这不起作用。它编译,但是无数是空的!为什么呢?
答案 0 :(得分:6)
List实现了IEnumerable,所以你不需要强制转换它们,你只需要这样做就可以使你的方法接受一个泛型参数,如下所示:
public static void VerifyNotNullOrEmpty<T>(this IEnumerable<T> 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<string>
{
"Test1",
"Test2"
};
myList.VerifyNotNullOrEmpty("myList", "My position");
您还可以稍微改进实施:
public static void VerifyNotNullOrEmpty<T>(this IEnumerable<T> 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));
}
}
答案 1 :(得分:5)
IEnumerable<object>
不是IEnumerable<T>
的超类型,因此它也不是List<T>
的超类型。请参阅question 2575363以简要了解为什么会出现这种情况(它与Java有关,但概念相同)。顺便提一下,这个问题在C#4.0中得到了解决,supports covariant generics。
您没有发现此错误的原因是您使用x as T
,您应该使用普通演员((T)x
),请参阅question 2139798。生成的InvalidCastException
会指出您的错误。 (事实上,如果类型关系是正确的(即如果IEnumerable<object>
是List<T>
的超类型),则根本不需要演员。)
要解决您的问题,请将您的方法设为通用,以便接受IEnumerable<T>
而不是IEnumerable<object>
,并完全跳过转换。
public static void VerifyNotNullOrEmpty<T>(IEnumerable<T> theIEnumerable,
string theIEnumerableName,
string theVerifyingPosition) { ... }
答案 2 :(得分:4)
假设您至少定位到框架3.0:
使用扩展程序转换为通用IEnumerable<object>
:
var myEnumerable = myList.Cast<object>();
编辑: 无论如何,我建议你改变你的方法来获得一个纯粹的IEnumerable,如:
public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable,
string theIEnumerableName,
string theVerifyingPosition)
并在方法内部使用foreach或theIEnumerable.Cast<object>().Count()
通过这种方式,您不必每次都投射到IEnumerable<object>