首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么这个字符串扩展方法没有抛出异常呢?

为什么这个字符串扩展方法没有抛出异常呢?
EN

Stack Overflow用户
提问于 2015-05-12 03:31:51
回答 2查看 7.4K关注 0票数 120

我有一个C#字符串扩展方法,它应该返回一个字符串中子字符串的所有索引的IEnumerable<int>。它完美地达到了预期的目的,并返回了预期的结果(我的一个测试证明了这一点,但不是下面的那个),但是另一个单元测试发现了它的一个问题:它不能处理null参数。

下面是我正在测试的扩展方法:

代码语言:javascript
复制
public static IEnumerable<int> AllIndexesOf(this string str, string searchText)
{
    if (searchText == null)
    {
        throw new ArgumentNullException("searchText");
    }
    for (int index = 0; ; index += searchText.Length)
    {
        index = str.IndexOf(searchText, index);
        if (index == -1)
            break;
        yield return index;
    }
}

下面的测试指出了这个问题:

代码语言:javascript
复制
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Extensions_AllIndexesOf_HandlesNullArguments()
{
    string test = "a.b.c.d.e";
    test.AllIndexesOf(null);
}

当测试针对我的扩展方法运行时,它会失败,并显示标准错误消息,表明该方法“未抛出异常”。

这很令人困惑:我明确地将null传递给了函数,但是由于某些原因,比较null == null返回false。因此,不会抛出异常,代码会继续执行。

我已经确认这不是测试的bug :在我的主项目中通过调用空比较if块中的Console.WriteLine来运行该方法时,控制台上没有显示任何内容,并且我添加的任何catch块都没有捕获任何异常。此外,使用string.IsNullOrEmpty而不是== null也有同样的问题。

为什么这种所谓的简单比较会失败呢?

EN

回答 2

Stack Overflow用户

发布于 2015-05-12 03:36:41

你有一个迭代器块。该方法中的任何代码都不会在返回的迭代器上对MoveNext的调用之外运行。调用该方法只会创建状态机,而且永远不会失败(除了内存不足错误、堆栈溢出或线程中止异常等极端情况之外)。

当你实际尝试迭代序列时,你会得到异常。

这就是为什么LINQ方法实际上需要两个方法来获得它们所需的错误处理语义。它们有一个私有方法,它是一个迭代器块,然后是一个非迭代器块方法,它只做参数验证(这样它就可以立即完成,而不是被推迟),同时仍然推迟所有其他功能。

所以这就是一般的模式:

代码语言:javascript
复制
public static IEnumerable<T> Foo<T>(
    this IEnumerable<T> souce, Func<T, bool> anotherArgument)
{
    //note, not an iterator block
    if(anotherArgument == null)
    {
        //TODO make a fuss
    }
    return FooImpl(source, anotherArgument);
}

private static IEnumerable<T> FooImpl<T>(
    IEnumerable<T> souce, Func<T, bool> anotherArgument)
{
    //TODO actual implementation as an iterator block
    yield break;
}
票数 34
EN

Stack Overflow用户

发布于 2015-06-01 22:07:37

正如其他人所说,枚举器直到它们开始被枚举(即调用IEnumerable.GetNext方法)时才会被计算。因此这是

代码语言:javascript
复制
List<int> indexes = "a.b.c.d.e".AllIndexesOf(null).ToList<int>();

直到开始枚举时才会进行计算,即

代码语言:javascript
复制
foreach(int index in indexes)
{
    // ArgumentNullException
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30176121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档