通用列表作为 IEnumerable;

发布于 2024-09-02 19:02:28 字数 1084 浏览 4 评论 0原文

我正在尝试将 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);

        }
    }

但是,这不起作用。它可以编译,但 IEnumerable 为空!为什么?

I'm trying to do cast a List to an IEnumerable, so I can verify that different lists are not null or empty:

Suppose myList is a List < T > . Then in the caller code I wanted:

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

The valdiating code would be:

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

        }
    }

However, this doens't work. It compiles, but theIEnumerable is null! Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请你别敷衍 2024-09-09 19:02:28

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

    }
}

List implements IEnumerable so you don't need to cast them, you just need to make it so your method accepted a generic parameter, like so:

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

    }
}

You should just be able to call it with:

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

myList.VerifyNotNullOrEmpty("myList", "My position");

You could also improve the implementation slightly:

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

    }
}
万水千山粽是情ミ 2024-09-09 19:02:28

IEnumerable不是 IEnumerable 的超类型,因此它也不是 List 的超类型。请参阅问题 2575363,简要概述为什么这是case(与Java有关,但概念是相同的)。顺便说一句,这个问题已在 C# 4.0 中得到解决,支持协变泛型

您没有发现此错误的原因是因为您使用了x as T,而您应该使用普通的强制转换((T)x),请参阅< a href="https://stackoverflow.com/questions/2139798/why-is-the-c-as-operator-so-popular">问题 2139798。生成的 InvalidCastException 会指出您的错误。 (事实上​​,如果类型关系正确(即如果 IEnumerableList 的超类型),则根本不需要强制转换.)

要解决您的问题,请使您的方法通用,以便它接受 IEnumerable 而不是 IEnumerable,并完全跳过强制转换。

 public static void VerifyNotNullOrEmpty<T>(IEnumerable<T> theIEnumerable,
                                            string theIEnumerableName,
                                            string theVerifyingPosition) { ... }

IEnumerable<object> is not a supertype of IEnumerable<T>, so it is not a supertype of List<T> either. See question 2575363 for a brief overview of why this is the case (it's about Java, but the concepts are the same). This problem has been solved in C# 4.0, by the way, which supports covariant generics.

The reason why you didn't find this error is because you used x as T, where you should have been using a normal cast ((T)x), see question 2139798. The resulting InvalidCastException would have pointed you at your error. (In fact, if the type relationship were correct (i.e. if IEnumerable<object> were a supertype of List<T>), you wouldn't need a cast at all.)

To solve your problem, make your method generic, so that it accepts an IEnumerable<T> instead of an IEnumerable<object>, and skip the cast completely.

 public static void VerifyNotNullOrEmpty<T>(IEnumerable<T> theIEnumerable,
                                            string theIEnumerableName,
                                            string theVerifyingPosition) { ... }
回忆躺在深渊里 2024-09-09 19:02:28

假设您的目标至少是框架 3.0:

使用扩展名转换为通用 IEnumerable

var myEnumerable = myList.Cast<object>();

编辑:
无论如何,我建议您更改方法以获取纯 IEnumerable,例如:

public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable,
                                        string theIEnumerableName,
                                        string theVerifyingPosition)

并在方法内部使用 foreach 或 theIEnumerable.Cast().Count() 检查是否为空,

这样您不必每次都转换为 IEnumerable

Supposing you're targeting at least framework 3.0:

Cast to a generic IEnumerable<object> using extension:

var myEnumerable = myList.Cast<object>();

EDIT:
anyway I'd suggest you to change your method to get a pure IEnumerable like:

public static void VerifyNotNullOrEmpty(IEnumerable theIEnumerable,
                                        string theIEnumerableName,
                                        string theVerifyingPosition)

and inside the method check if empty using foreach or theIEnumerable.Cast<object>().Count()

In this way you don't have to cast every time to IEnumerable<object>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文