通用列表<t>为IEnumerable <object> </object> </t>

时间:2010-05-20 12:07:39

标签: c# casting ienumerable generic-list

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

假设myList是List&lt; 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);

        }
    }

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

3 个答案:

答案 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>