代码之家  ›  专栏  ›  技术社区  ›  Avi

作为IEnumerable<object>

  •  3
  • Avi  · 技术社区  · 16 年前

    我正在尝试将列表强制转换为IEnumerable,以便验证不同的列表是否为null或空:

    假设myList是一个列表<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 回复  |  直到 14 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    IEnumerable<object> 不是的超类型 IEnumerable<T> List<T> 任何一个。看到了吗 question 2575363 supports covariant generics .

    您没有找到此错误的原因是您使用了 x as T ,你应该用普通的石膏( (T)x question 2139798 . 结果 InvalidCastException 是一种超型的 列表<T> ),你根本不需要石膏。)

    要解决您的问题,请使您的方法泛型化,以便它接受 IEnumerable<T> 而不是 IEnumerable<对象>

     public static void VerifyNotNullOrEmpty<T>(IEnumerable<T> theIEnumerable,
                                                string theIEnumerableName,
                                                string theVerifyingPosition) { ... }
    
        2
  •  6
  •   Dave D    16 年前

    列表实现了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));
    
        }
    }
    
        3
  •  4
  •   digEmAll    16 年前

    假设您的目标至少是framework 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()

    这样你就不用每次都投