2010-05-06 39 views
5

我有一些代码有以下逻辑:使用Contract.Assert(true)时该怎么办,该方法必须返回什么?

//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!"); 

的问题是,由于此方法返回的东西,和编译器不明白断言会破坏程序的执行。在使用合同之前,在这种情况下,我曾经抛出异常,解决了这个问题。你如何处理这与Contract.Assert()?在Contract.Assert()调用后返回null或default(element_type)知道它永远不会被调用并关闭编译器?或者还有没有其他更优雅的方式来做到这一点?

感谢

+0

不要你的意思'Contract.Assert(假的, “无效的状态!”);'? – 2010-08-03 14:38:16

+0

是的,我做过了。 :facep: – 2010-08-03 15:47:01

回答

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

但会遍历整个列表了。

+0

关于使用LINQ的First,是否会运行整个elementList,或者它会在找到第一个元素的那一刻停止搜索更多元素? – 2010-05-06 07:07:24

+1

@devoured我认为,因为我写它会运行整个列表。但是可能将它用作'elementList.First(e => e是什么)'(注意缺少'Where')应该停在第一个。但我没有测试它 – 2010-05-06 07:10:02

+0

Oooooooops。我误点了“接受答案按钮”,并对你投了反对票。你必须编辑你的答案,所以它允许我改变投票:( – 2010-05-06 07:17:04

1

我想你会比在这里的Contract.Assert更好一个Contract.Requires(即一个先决条件)。你的代码片段的前提条件是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); 
+0

- ,所以你必须在列表中遍历两次......这不是顶级的樱桃......你甚至使用'.Count()> 0'(属性调用是不可能的,因为'.Where()'的返回值是'IEnumerable ',并且该类型没有属性'.Count',而是一个扩展方法...'Enumerable.Count()')需要遍历整个结果 - 而不是使用'.Any()' – 2012-11-02 06:51:09

+0

没有。有人不明白契约是如何工作的。无论何时速度很重要,我的答案遍历列表最多一次。前提条件使得代码更具可读性,有助于调试,并可作为优化器的提示。它不在生产代码中执行。 – 2012-11-13 03:38:54

+0

没有。有人不明白Linq是如何工作的(请阅读http://stackoverflow.com/questions/305092/which-method-performs-better-any-vs-count-0),并且“Count”属性不存在'IEnumerable ' - 然而,'Contract.Require'的执行是一个配置问题(又称'Perform Runtime Contract Checking':**'Full' **,'Pre and Post',...)。 – 2012-11-13 07:07:43