在阅读了有关此类问题的其他一些答案后,我仍然得到警告。在此代码段中,我从数据库中提取了一个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;
}
最佳答案
我会尝试使用其他方法,也许避免使用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。关于c# - 代码契约(Contract):需要未经证实的来源!= null,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8646954/