5

我有一些具有以下逻辑的代码:

//pseudo-code
foreach (element in elementList) {
    if (element is whatever)
        return element;
    }
}

理论上,总有一个元素是什么,所以这种方法应该没有问题。无论如何,为了确定,我在方法的末尾添加了一个断言:

//pseudo-code
foreach (element in elementList) {
    if (element is whatever)
        return element;
    }
}

Contract.Assert(false, "Invalid state!");

问题是这个方法必须返回一些东西,编译器不明白断言会破坏程序的执行。在使用 Contracts 之前,在这种情况下,我曾经抛出一个异常,从而解决了问题。你将如何使用 Contract.Assert() 处理这个问题?在 Contract.Assert() 调用之后返回 null 或 default(element_type) 知道它永远不会被调用并关闭编译器?或者还有其他更优雅的方法吗?

谢谢

4

2 回答 2

2

你可以和

var result = null;
foreach (element in elementList) {
    if (element is whatever)
        result = element;
        break;
    }
}

Contract.Assert(result != null, "Invalid state!");
return result;

它引入了一个休息,但它确实在返回周围看起来更干净。

甚至更清洁

return elementList.Where( e => e is whatever).First();

编辑为@devoured 指出以上内容会影响整个列表

无所不在的清洁工

return elementList.First( e => e is whatever);

结束编辑

如果什么也没找到,那只会爆炸。

但如果你真的想要断言它可能是

var results = elementList.Where( e => e is whatever);
Contract.Assert(results.Count() == 1, "Boo");
return results.First();

但这也会迭代整个列表。

于 2010-05-06T07:03:25.833 回答
1

我认为你最好使用 a Contract.Requires(即前提条件)而不是 a Contract.Assert。您的代码段的前提条件是 elementList 至少包含一个符合条件的元素。

您应该明确这一点,而不是依赖Assert(false),这需要读者理解函数的其余部分并遵循流控制来推断Assert(false)达到的情况。

所以,我会重写为:

//precondition (checked only in debug builds)
Contract.Require(elementList.Where(e => e is whatever).Count > 0,"elementList requires at least one element meeting condition whatever");
//do work (throws in release builds, never reached in debug ones)
return elementList.First( e => e is whatever);
于 2010-08-03T14:46:16.600 回答