通用列表<T>为IEnumerable <object>

Avi*_*Avi 3 c# ienumerable casting generic-list

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

假设myList是List <T>.然后在我想要的来电代码中:

       Validator.VerifyNotNullOrEmpty(myList as IEnumerable<object>,
                                     @"myList",
                                     @"ClassName.MethodName");
Run Code Online (Sandbox Code Playgroud)

有价值的代码是:

     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);

        }
    }
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*wns 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);

    }
}
Run Code Online (Sandbox Code Playgroud)

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

var myList = new List<string>
{
    "Test1",
    "Test2"
};

myList.VerifyNotNullOrEmpty("myList", "My position");
Run Code Online (Sandbox Code Playgroud)

您还可以稍微改进实施:

 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));

    }
}
Run Code Online (Sandbox Code Playgroud)


Hei*_*nzi 5

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

您没有找到此错误的原因是因为您使用过x as T,您应该使用普通的cast((T)x),请参阅问题2139798.结果InvalidCastException会指出你的错误.(事实上​​,如果类型关系是正确的(即,如果IEnumerable<object>是超类型List<T>),你根本不需要演员.)

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

 public static void VerifyNotNullOrEmpty<T>(IEnumerable<T> theIEnumerable,
                                            string theIEnumerableName,
                                            string theVerifyingPosition) { ... }
Run Code Online (Sandbox Code Playgroud)