给定以下界面:

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# - 开放式通用约束-LMLPHP

希望对您有所帮助。

关于c# - 开放式通用约束,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33073633/

10-15 03:11