当我试图使这段代码证明错误时,我将从强制转换中获得多少性能损失?

本文关键字:转换 损失 性能 多少 段代码 错误 证明 代码 | 更新日期: 2023-09-27 18:11:06

我有以下代码:

public class CrudModel<T> : ICrudModel<T> where T : DomainBase
{
    public IQueryable<T> GetAll()
    {
        return Repository.Query<T>();
    }
}

问题是,一些对象(T)我需要做一个额外的过滤器,所以我创建了一个单独的方法,像这样:

public IEnumerable<TR> GetAllwithinOrg<TR>() where TR : DomainBase, IFilterable
{
    var items = Repository.Query<TR>();
    return FilterwithinOrg(items);
}

,其中过滤器方法看起来像这样:

public IEnumerable<TResult> FilterwithinOrg<TResult>(IEnumerable<TResult> linked) where TResult :  IFilterable
{
    var dict = GetDict();
    return linked.Where(r => dict.ContainsKey(r.Id));
}

这一切都很好,但问题是,我必须记住调用方法1或方法2(基于对象是否支持IFilterable接口

在这个问题上,我得到的建议是:
public IQueryable<T> GetAll()
{
    var items = Repository.Query<T>();
    if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
    {
        items = FilterwithinOrg(items.Cast<IFilterable>()).Cast<T>().AsQueryable();
    }
    return items;
}

所以我可以在一个方法中支持两个用例。这似乎是有效的,但我试图理解我将采取什么类型的性能打击通过执行这个

items.Cast<IFilterable>()).Cast<T>().AsQueryable()

如果它很糟糕,那么我将处理记住从外部调用两个单独的方法,但显然只有一个方法会很方便。有什么建议吗?

我想如果我忘记调用第二个方法,我会把它作为备份,但是我想再看看我是否可以只保留一个方法,如果可能的话,让外部调用者更简单。

当我试图使这段代码证明错误时,我将从强制转换中获得多少性能损失?

在CrudModel类中使用where子句的另一个方法如何?

public IEnumerable<T> GetAll<T>(Func<T, bool> whereClause) where T : DomainBase
{
    var items = Repository.Query<T>();
    return items.Where(whereClause);
}

和调用

List<int> intList = new List<int>() { 1 };
intList.GetAll<int>((i) => sampledict.ContainsKey(i));

我觉得把逻辑挤进一个单一的GetAll方法使事情变得复杂是不合适的,因为CrudModel似乎是通用的,最好有接受任何条件的通用方法。

首先,我认为你有一个函数GetAll有点奇怪,但是对于某些类型,你开始过滤,导致没有得到全部:)

除此之外,我不认为你有很大的性能损失…实际上你在你的GetAll里面做了一个额外的检查——方法:typeof(IFilterable).IsAssignableFrom(typeof(T))就像一个普通的cast。你几乎感觉不到。

也许过滤器本身可以改进。创建一个字典。字典是否每次调用都有相同的值,或者是否会改变。如果只使用键而不使用值,为什么要使用字典呢?那HashSet<T>

与数据库查询所花费的时间相比,可以忽略类型转换时间。但是,您是根据下面的代码在内存中查询整个表和过滤器:

public IEnumerable<TResult> FilterwithinOrg<TResult>(IEnumerable<TResult> linked) where TResult :  IFilterable
{
    var dict = GetDict();
    return linked.Where(r => dict.ContainsKey(r.Id));
}

请记住,您需要过滤查询,而不是列表,因此您应该更改方法以接受并返回IQueryable<TResult>,如:

public IQueryable<TResult> FilterwithinOrg<TResult>(IQueryable<TResult> linked) where TResult :  IFilterable
{
    var dictKeys = GetDict().Keys.ToList();
    return linked.Where(r => dictKeys.Contains(r.Id));
}

请注意,过滤器表达式必须具有等效的SQL表达式,否则将发生运行时错误。