C# 关于两种不同的类扩展模式的问题

C# 关于两种不同的类扩展模式的问题,c#,.net,extension-methods,C#,.net,Extension Methods,以下两种方法的语义区别是什么: public static bool IsNullOrEmpty(this Array value) { return (value == null || value.Length == 0); } 及 publicstaticbool为空(此T[]值) { 返回值(value==null | | value.Length==0); } 一个比另一个有优势吗?第二个使用泛型,因此是类型安全的。使用泛型,您可以添加一个条件,进一步限制T可以是什么 因此,

以下两种方法的语义区别是什么:

public static bool IsNullOrEmpty(this Array value)
{
    return (value == null || value.Length == 0);
}

publicstaticbool为空(此T[]值)
{
返回值(value==null | | value.Length==0);
}

一个比另一个有优势吗?

第二个使用泛型,因此是类型安全的。

使用泛型,您可以添加一个条件,进一步限制T可以是什么

因此,您可以使用“where T:class”或“where T:isompointerface”来限制它(最值得注意的是您可以使用“where T:IDisposable”并确保您的扩展不能使用任何无法处理的内容。第一种方法适用于任何数组,包括矩形数组和具有非零下限的数组。当数组的编译时类型仅为
array
时,它也会起作用,这在类型相当弱的API中偶尔会发生

简言之,第一种方法更具普遍性,应该适用于第二种方法的任何地方

(我假设您不希望从中获得任何“额外”功能,例如第二种形式中对
t
的额外约束……您只需要一些东西来确定数组引用是null还是引用空数组。)

编辑:对于
IEnumerable
,您将使用:

public static bool IsNullOrEmpty(this IEnumerable value)
{
    if (value == null)
    {
        return true;
    }
    var iterator = value.GetEnumerator();
    try
    {
        return !iterator.MoveNext();
    }
    finally
    {
        // Non-generic IEnumerator doesn't extend IDisposable
        IDisposable disposable = iterator as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}

当然,这样做的缺点是很容易产生副作用——例如,您可以传入一个LINQ查询,该查询最终会与数据库进行对话。

那么,第一个查询的后果是什么(即可能出现的错误)?由于方法体中没有使用任何值,因此很难看出基于元素的类型安全性是如何相关的。因此,第一种模式是首选模式吗?@IanC:如果您只想以数组为目标,可以。如果您想处理任何序列,可以采用
IEnumerable
,使其更为通用。您在这方面是正确的我不需要任何额外的功能。这是string.IsNullOrEmpty(str)的功能等价物。我如何实现IEnumerable?它没有计数或任何检查此类功能的工具。谢谢。根据您所说的,我想我现在就把它放在ICollection上。它以一种通用的方式满足我的需要,这就是我想要的。
public static bool IsNullOrEmpty(this IEnumerable value)
{
    if (value == null)
    {
        return true;
    }
    var iterator = value.GetEnumerator();
    try
    {
        return !iterator.MoveNext();
    }
    finally
    {
        // Non-generic IEnumerator doesn't extend IDisposable
        IDisposable disposable = iterator as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}