在阅读了对此类问题的其他一些回复之后,我仍然留下了警告。在这个片段中,我从我的数据库中提取UserActivation。到目前为止,总会有至少一个UserActivation。如果有更多的东西已经全部变成了梨形状...我遵循了一些其他说明如何压制关于未经证实的来源的警告但无效。警告是:警告83 CodeContracts:要求未经证实:source!= null在第161行,请参阅下面的具体行的方法。
这是方法
private static UserActivation GetUserActivation(Guid userId)
{
UserActivations userActivations = UserActivation.GetUserActivationsByUser(userId: userId);
Contract.Assume(userActivations != null);
if (userActivations.Count() > 1) // Line Number 161
throw new Exception("More then one user action found in database");
return userActivations[0];
}
我使用的是CC版本1.4.40602.0,这里要求的是UserActivations声明。
public class UserActivations : BusinessListBase<UserActivation>
{
#region Constructors
internal UserActivations()
{
}
internal UserActivations(IList<UserActivation> list)
: base(list)
{
}
internal UserActivations(IEnumerable<UserActivation> list)
: base(list)
{
}
这是GetUserActivationByUser方法
public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid())
{
Contract.Requires(user != null || userId != null, "Either user or userId must have a value");
Contract.Ensures(Contract.Result<UserActivations>() != null);
Guid id = new Guid();
if (user != null)
id = user.Id;
else
id = userId;
return new UserActivations(StorageManager.SelectAll(
Criteria.And(
Criteria.EqualTo("UserId", id),
Criteria.EqualTo("Deleted", false))));
}
原始代码是:
Public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid())
{
Guid id = new Guid();
if (user != null)
id = user.Id;
else
if (userId != Guid.Empty)
id = userId;
else
throw new Exception("Either user or userId must have a value");
UserActivations uas = new UserActivations(StorageManager.SelectAll(
Criteria.And(
Criteria.EqualTo("UserId", id),
Criteria.EqualTo("Deleted", false))));
Contract.Ensures(Contract.Result<UserActivations>() != null);
return uas;
}
答案 0 :(得分:4)
我会尝试使用不同的方法,也许避免使用linq Enumerable
扩展方法。 UserActivations
类是否有自己的方法或属性来确定实例保存的元素数量?
无论如何,您不应使用Count()
扩展方法来测试序列是否为空,因为它将枚举整个序列(如果序列未实现ICollection
)。或者,正如Pavel Gatilov指出的那样,如果对象实现IQueryable
,则Count可能会意外地执行数据库查询。
这里没什么大不了的,你期望有一个元素,但在一个序列可能经常有数千个元素的情况下,它可能是一个大问题。相反,您应该使用Any()
扩展方法。
因为使用Any()
可能不会改变合同分析器的观点,所以你应该使用UserActivations类的Count
属性(假设它实现了ICollection)。
也许您可以通过这种方式帮助合同分析器:
private static UserActivation GetUserActivation(Guid userId)
{
UserActivations userActivations = UserActivation.GetUserActivationsByUser(userId: userId);
IEnumerable<UserActivation> e = (IEnumerable<UserActivation>)userActivations;
Contract.Assume(e != null);
if (e.Count() > 1) // Line Number 161
throw new Exception("More then one user action found in database");
return userActivations[0];
}
如果您控制UserActivations
类,更好的解决方案是将Contract.Ensures
添加到GetUserActivationsByUser
,以表明该方法永远不会返回null。
答案 1 :(得分:2)
检查您的构建日志。您错误地使用了Contract.Ensures
。您应该对错误的使用情况发出警告,例如:
警告CC1025:CodeContracts:在合同块之后,发现使用合同块中定义的局部变量'dataEvents'
你的方法应该是:
public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid())
{
Contract.Ensures(Contract.Result<UserActivations>() != null);
Guid id = new Guid();
if (user != null)
id = user.Id;
else
if (userId != Guid.Empty)
id = userId;
else
throw new Exception("Either user or userId must have a value");
UserActivations uas = new UserActivations(StorageManager.SelectAll(
Criteria.And(
Criteria.EqualTo("UserId", id),
Criteria.EqualTo("Deleted", false))));
return uas;
}
我无法证明,但我想这可能会让验证者发疯。
事实上,如果我打开运行时检查,你的代码甚至都不会编译:ccrewrite会失败。