2010-05-20 53 views
3

我试图做投列表为IEnumerable,所以我可以确认的是不同的列表是不为空或为空:泛型列表<T>为IEnumerable <object>

假设myList中是一个List < T>。然后在调用者的代码,我想:

 Validator.VerifyNotNullOrEmpty(myList as IEnumerable<object>, 
            @"myList", 
            @"ClassName.MethodName"); 

的valdiating代码将是:

 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

做任何答案都有帮助吗? – 2010-12-23 23:31:49

+0

@Dave - 哎呀。抱歉。很好的答案。接受Heinzi的,因为它更关注为什么我的代码不起作用,但你清楚地向我解释了什么应该工作。谢谢! – Avi 2011-01-04 02:00:39

回答

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) { ... } 
+0

在这种情况下,您无法投射'(IEnumerable )myList'。 – Kobi 2010-05-20 12:39:40

+0

@Kobi:是的,正是我的观点:如果你使用'(IEnumerable )myList',你会得到一个'InvalidCastException',并立即知道你使用的是错误的类型。如果你使用'myList作为IEnumerable ',你还是想知道为什么结果是null(“myList null?或者演员失败?”)。 – Heinzi 2010-05-20 12:43:09

+0

好的。我误解了你;你似乎建议铸造可能在这里工作。 – Kobi 2010-05-20 12:53:55

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>

+0

不工作:-( 来电现在要求: Validator.VerifyNotNullOrEmpty(myList.Cast (),... 被叫仍收到了IEnumerable theIEnumerable为空 – Avi 2010-05-20 12:19:01

+0

你肯定myList中不为空 – digEmAll 2010-05-20 12:22:42

6

列表实现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)); 

    } 
} 
+0

这一次大概是?更好 - 它演示了如何编写一个通用的扩展方法,当然,代码很奇怪 - 在'errMsg'中添加文本在这里是没用的,但除此之外,还要注意'Count()可能会迭代整个集合,这可能不是我想要的,我更喜欢'.Any()'来检查是否有任何项目可用,尽管这可能也有副作用 – Kobi 2010-05-20 12:22:23

+0

我同意errMsg,但我并不是真的想要改变他的实际执行时,只是改变签名将做他所需要的... – 2010-05-20 12:25:35

+0

我的错误 - 错误消息进入新的异常,所以它做了一些事情。错过了那一点:P。仍然有两种不同类型的例外是优选的。 – Kobi 2010-05-20 12:28:14

相关问题