有什么重要的理由要避免 `as IQueryable` 吗?
Any significant reason to avoid `as IQueryable`?
我有一个模型到视图模型映射扩展方法库。支持它们的是一个基础 class 和一些常用方法,包括 Transform
,如下:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
var queryable = value as IQueryable<TOriginal> ?? value.AsQueryable();
return queryable.Select(Expression);
}
我的问题:除了可以忽略不计的性能影响之外,是否有任何重要的理由让我应该避免上面的 as IQueryable
强制转换?例如,我可以改为执行以下操作:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IQueryable<TOriginal> value)
{
return value.Select(Expression);
}
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
...但我宁愿不必在我的每个依赖 classes 中都编写重载。编辑:澄清一下,这是我要避免的示例:
public static class TransformCompany
{
private static readonly TransformBase<Organization, CompanyHeader> header = new TransformPrecompiled<Organization, CompanyHeader>(
company => new CompanyHeader
{
Name = company.Name,
});
public static IQueryable<CompanyHeader> AsHeaders(this IQueryable<Organization> companies)
{
return header.Transform(companies);
}
// Note I have to include this capability in each of my dependent classes
// Worse is the possibility that someone may accidentally implement
// only IEnumerable for a future model transformation,
// causing a hidden data performance problem
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
Queryable.AsQueryable Method (IEnumerable)
If the type of source implements IQueryable,
AsQueryable(IEnumerable) returns it directly. Otherwise, it returns an
IQueryable that executes queries by calling the equivalent query
operator methods in Enumerable instead of those in Queryable.
您将 Transform
方法简化为
,而不是转换
return value.AsQueryable().Select(Expression);
我会说你不需要 IEnumerable<T>
和 IQueryable<T>
的单独扩展,因为 IQueryable<T>
继承自 IEnumerable<T>
,你也不需要强制转换。
查看 referencesource,AsQueryable()
实际上会为您检查:
public static IQueryable<TElement> AsQueryable<TElement>(this IEnumerable<TElement> source)
{
if (source == null)
throw Error.ArgumentNull("source");
if (source is IQueryable<TElement>)
return (IQueryable<TElement>)source;
return new EnumerableQuery<TElement>(source);
}
因此,以下内容应该对您有用且不会影响性能:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
}
public static class TransformCompany
{
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
}
我有一个模型到视图模型映射扩展方法库。支持它们的是一个基础 class 和一些常用方法,包括 Transform
,如下:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
var queryable = value as IQueryable<TOriginal> ?? value.AsQueryable();
return queryable.Select(Expression);
}
我的问题:除了可以忽略不计的性能影响之外,是否有任何重要的理由让我应该避免上面的 as IQueryable
强制转换?例如,我可以改为执行以下操作:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IQueryable<TOriginal> value)
{
return value.Select(Expression);
}
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
...但我宁愿不必在我的每个依赖 classes 中都编写重载。编辑:澄清一下,这是我要避免的示例:
public static class TransformCompany
{
private static readonly TransformBase<Organization, CompanyHeader> header = new TransformPrecompiled<Organization, CompanyHeader>(
company => new CompanyHeader
{
Name = company.Name,
});
public static IQueryable<CompanyHeader> AsHeaders(this IQueryable<Organization> companies)
{
return header.Transform(companies);
}
// Note I have to include this capability in each of my dependent classes
// Worse is the possibility that someone may accidentally implement
// only IEnumerable for a future model transformation,
// causing a hidden data performance problem
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
Queryable.AsQueryable Method (IEnumerable)
If the type of source implements IQueryable, AsQueryable(IEnumerable) returns it directly. Otherwise, it returns an IQueryable that executes queries by calling the equivalent query operator methods in Enumerable instead of those in Queryable.
您将 Transform
方法简化为
return value.AsQueryable().Select(Expression);
我会说你不需要 IEnumerable<T>
和 IQueryable<T>
的单独扩展,因为 IQueryable<T>
继承自 IEnumerable<T>
,你也不需要强制转换。
查看 referencesource,AsQueryable()
实际上会为您检查:
public static IQueryable<TElement> AsQueryable<TElement>(this IEnumerable<TElement> source)
{
if (source == null)
throw Error.ArgumentNull("source");
if (source is IQueryable<TElement>)
return (IQueryable<TElement>)source;
return new EnumerableQuery<TElement>(source);
}
因此,以下内容应该对您有用且不会影响性能:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
}
public static class TransformCompany
{
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
}