给定以下界面:
public interface IQuerySpec<M> { }
我很想做一个这样的扩展方法:
public static OrderedSortation<T> OrderBy<T, TKey>(
this T query,
Expression<Func<T, TKey>> sort)
where T : IQuerySpec<?> {
//business as usual
}
我只想确保
T
类型是IQuerySpec<M>
的某种变体。然后,我可以按以下方式调用扩展方法:public class Foo : IQuerySpec<int> {
public int SizeOfSailBoat {get; set;}
}
IQuerySpec<Foo> foo = new Foo {SizeOfSailBoat = 10}.
var result = foo.OrderBy(f => f.SizeOfSailBoat);
在上面的示例中指定了UDT
Foo
,但是我不在乎使用了什么泛型类型参数。有没有办法做到这一点?
我尝试了以下方法:
public static OrderedSortation<T> OrderBy<T, M, TKey>(
this T query,
Expression<Func<T, TKey>> sort)
where T : IQuerySpec<M> {
//business as usual
}
上面的方法有效,但要求显式声明通用参数才能调用“OrderBy”。我不需要明确声明通用参数。
我也尝试过这个:
public interface IQuerySpec {}
public interface IQuerySpec<M> : IQuerySpec {}
使用这些接口(interface),我可以执行以下操作:
public static OrderedSortation<T> OrderBy<T, TKey>(
this T query,
Expression<Func<T, TKey>> sort)
where T : IQuerySpec {
//business as usual
}
这几乎够好了,除了我想隐藏非通用的IQuerySpec,以使其在我的类库之外不可见。我希望能以这种方式确定非通用接口(interface)的范围:
internal interface IQuerySpec {}
不幸的是,编译器不允许我这样做。
我想我想要的是不可能的,但只是以防万一。
最佳答案
问题是编译器无法从T隐式推断M的类型或从M隐式推断T的类型。
所以您需要修复一个,这里我将T修复为IQuerySpec<M>
扩展方法的签名变为
public static OrderedSortation<IQuerySpec<M>> OrderBy<M, TKey>(
this IQuerySpec<M> query,
Expression<Func<IQuerySpec<M>, TKey>> sort)
{
//business as usual
}
举个例子
class IntQSpec : IQuerySpec<int>
{
//your implementation
}
这是调用示例
var iQS = new IntQSpec();
//do whatever you want with iQS
var ord = iQS.OrderBy(ii=>ii.ToString());
//here I called OrderBy without the need to explicitly specifying the Generic Arguments
这是您的代码在Visual Studio 2013-2015上的测试,突出显示的地方没有错误
请注意,我访问了具体类型
IntQSpec
的Z字段希望对您有所帮助。
关于c# - 开放式通用约束,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33073633/