Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以在IQueryable和IEnumerable上签合同吗?_C#_.net_Ienumerable_Iqueryable_Code Contracts - Fatal编程技术网

C# 我可以在IQueryable和IEnumerable上签合同吗?

C# 我可以在IQueryable和IEnumerable上签合同吗?,c#,.net,ienumerable,iqueryable,code-contracts,C#,.net,Ienumerable,Iqueryable,Code Contracts,让我们看看下面的代码: public IQueryable<Category> GetAllActive() { Contract.Ensures(Contract.Result<IQueryable<Category>>() != null); return dataSource.GetCategories(T => T.IsActive); } public IQueryable GetAllActive() { Contract.

让我们看看下面的代码:

public IQueryable<Category> GetAllActive()
{
    Contract.Ensures(Contract.Result<IQueryable<Category>>() != null);
    return dataSource.GetCategories(T => T.IsActive);
}
public IQueryable GetAllActive()
{
Contract.sure(Contract.Result()!=null);
返回dataSource.GetCategories(T=>T.IsActive);
}
有一个小问题。代码契约可以这样写吗:

public IQueryable<Category> GetAllActive()
{
    Contract.Ensures(Contract.Result<IQueryable<Category>>() != null);
    Contract.Ensures(Contract.Result<IQueryable<Category>>().All(T => T.IsActive));
    return dataSource.GetCategories(T => T.IsActive);
}
public IQueryable GetAllActive()
{
Contract.sure(Contract.Result()!=null);
Contract.survey(Contract.Result().All(T=>T.IsActive));
返回dataSource.GetCategories(T=>T.IsActive);
}
还是不


这样的事情会产生不必要的序列枚举吗?这是非常不需要的?

假设您正在使用二进制重写器并在运行时强制执行契约,您不应该这样做

当您这样使用时:

Contract.sure(Contract.Result());
返回表达式;
它被转换,操作被提升为如下内容:

T expression = <expression>;

// Perform checks on expression.
if (!(expression <operation>) <throw appropriate exception>;

// Return value.
return expression;
T表达式=;
//对表达式执行检查。
if(!(表达式);
//返回值。
返回表达式;
在这种情况下,这意味着您的代码将展开到:

IQueryable<Category> temp = dataSource.GetCategories(T => T.IsActive);

// Perform checks.
if (!(temp != null)) throw new Exception();
if (!temp.All(T => T.IsActive)) throw new Exception();

// Return values.
return temp;
IQueryable temp=dataSource.GetCategories(T=>T.IsActive);
//进行检查。
如果(!(temp!=null))抛出新异常();
如果(!temp.All(T=>T.IsActive))抛出新异常();
//返回值。
返回温度;
在这种情况下,您的请求将被迭代,并将导致另一个请求被发送到底层数据存储

根据操作的不同,您可能不会注意到它,但是查询肯定会执行两次,这对性能不利

对于这种性质的事情,您应该在
IQueryable
的使用点检查是否有任何元素(您可以使用一个布尔标志来执行此操作,该标志设置为您通过它进行
foreach
操作,或者当您具体化它时)


但是,如果您没有在编译的程序集上运行二进制重写器,那么这种性质的契约将无法强制执行;在这种情况下,它是一个noop,可能不应该在那里,因为它没有做任何事情。

如果您使用的是完整的运行时契约检查器,我看不出它如何避免强制执行枚举-还有其他方法吗uld可以检查吗?@Damien_不相信它。我没有使用运行时检查器。对我来说,现在,契约是一种让工具来测试我的代码是否存在简单的可能的逻辑冲突的方法。因此,如果你想要一个清楚的答案,你需要澄清你正在使用的契约系统的哪些部分。有很多选项可以打开。@Dam我不相信你,我只使用静态检查器。
IQueryable<Category> temp = dataSource.GetCategories(T => T.IsActive);

// Perform checks.
if (!(temp != null)) throw new Exception();
if (!temp.All(T => T.IsActive)) throw new Exception();

// Return values.
return temp;