我可以忽略C#接口中的泛型类型吗? 背景

我可以忽略C#接口中的泛型类型吗? 背景,c#,generics,interface,sieve.net,C#,Generics,Interface,Sieve.net,我正在着手一个叫做OSS的小程序库 签名允许某人定义一个筛,如下所示: new EqualitySieve<ABusinessObject>().ForProperty(x => x.AnInt); new EqualitySieve().ForProperty(x=>x.AnInt); 这实际上返回了一个筛选,但我已经尽了最大努力确保用户不必太在意这一部分 任务 我想找到一种方法,在这里放置一个接口,我根本不关心属性类型——只是它始终是一致的 因此,本质上,我希望能够声明

我正在着手一个叫做OSS的小程序库

签名允许某人定义一个
,如下所示:

new EqualitySieve<ABusinessObject>().ForProperty(x => x.AnInt);
new EqualitySieve().ForProperty(x=>x.AnInt);
这实际上返回了一个
筛选
,但我已经尽了最大努力确保用户不必太在意这一部分

任务 我想找到一种方法,在这里放置一个接口,我根本不关心属性类型——只是它始终是一致的

因此,本质上,我希望能够声明一个
ISieve
,并通过该接口定义如下内容:

ISieve<TFilterObjectType, TTypeIDontCareAbout> ForValue(TTypeIDontCareAbout);
iseveforvalue(ttypeidontcareaout);
我的目标是能够让类由
ISieve
而不是
ISieve
组成

问题:
  • 有没有一种方法可以让接口声明一个实际上是通配符的类型,并说“我不在乎这是什么类型,只是它是一致的?”
我最初的研究结果是否定的,但我希望被证明是错误的

更新和澄清 我真正想弄明白的是:

  • 我允许用户创建
    EqualitySieve().ForProperty(x=>x.AnInt)
  • 这实际上会向用户返回一个
    EqualitySieve
    ,但由于它是一个流畅的界面,我让他们不必关心这个部分
  • 我希望
    EqualitySieve
    LessThanSieve
    等实现
    ISieve
  • 我想
    ISieve可能有一些技巧,以便调用方不需要在泛型方法上指定类型(想想LINQ是如何工作的),但不幸的是,您的研究是正确的,在编写使用该类型的类时,无法推断类型

    最接近它的是有两层接口,外层不使用任何依赖于
    ttypeidontcareaout
    类型的函数

    interface ISieve<TFilterObjectType,TTypeIDontCareAbout> : ISieve<TFilterObjectType> 
    {
        TFilterObjectType ForValue(TTypeIDontCareAbout forValue);
    }
    
    interface ISieve<TFilterObjectType> 
    {
        TFilterObjectType SomeOtherFunction();
    }
    
    接口ISieve:ISieve
    {
    tFilterObject ForValue类型(tTypeIDontCareAuto ForValue);
    }
    接口ISieve
    {
    TFilterObjectType SomeOtherFunction();
    }
    

    我不知道如何解决你所有的问题,但我认为蒂莫西的方法正是你想要达到的两点

    • 我允许用户创建
      EqualitySieve().ForProperty(x=>x.AnInt)
    • 这实际上会向用户返回一个
      EqualitySieve
      ,但由于它是一个流畅的界面,我让他们不必关心这个部分
    接口ISieve
    {
    TFilterObjectType SomeOtherFunction();
    均衡器属性(函数选择器);
    EqualitySieve ForProperty(表达式选择器);//如果需要IQueryable支持,可以这样做。
    }
    
    您可以在接口和接口的方法上放置泛型类型参数。因此,下面的示例将定义一个通用接口,其中
    F
    方法采用其中一个“我不在乎这是什么类型,只是它是一致的”参数

    interface I<T>
    {
        //The generic type parameter U is independent of T.
        //Notice how F "forwards" the type U from input to output.
        Tuple<T, U> F<U>(U u);
    }
    
    用法:

    //Assuming MyObject.MyProperty is an int property
    //s has type EqualitySieve<MyObject, int>
    var s = Sieve.Equality<MyObject>().ForProperty(x => x.MyProperty);
    
    //假设MyObject.MyProperty是int属性
    //s型平衡筛
    var s=Sieve.Equality().ForProperty(x=>x.MyProperty);
    
    @Scott谢谢你抓住了这些打字错误。@ScottChamberlain说得好。我认为我没有恰当地说明我的目标,而是把重点放在一个技术问题上,而这个问题可能是一个设计问题。我要重新措辞。不幸的是,我要跳上一个航班,所以它可能需要等待一段时间。这取决于他所说的“一致性”,如果他是说“多个函数都使用相同的类型”,这将不起作用,但如果他是说“此函数中此变量的使用是一致的”,那么这将非常有效。@Timothy,感谢您的回复!抱歉等了这么久;我补充了一些澄清,希望对我的意图有所帮助。请让我知道任何我能澄清的事情。我感谢您的帮助。@SeanKilleen请查看我的更新,并告诉我是否更接近了。@TimothyShields肯定越来越接近了。我正在研究一个要点,以展示我现在要看的内容是否更有意义。本质上,我希望能够编写一些能够找到
    ISieve@SeanKilleen我查看了你的github资料,对你要做的事情有了更好的了解。看起来这个问题的范围可能比最初预期的要大,因为它实际上是关于如何设计库的核心,而不仅仅是“如何让泛型做这件事”。如果您愿意,我们可以通过不同的媒介继续讨论。我甚至可以在github上为它做贡献,因为这个想法很有趣。我想我至少可以帮你指明做这类事情的正确方向。谢谢。我认为这很可能是我澄清后的答案(见问题更新)。我只是希望会有一些诡计支持它。我在试着判断我所做的是否是某种设计的味道。对于可找到的筛子,人们只需要知道我认为的属性类型。@SeanKilleen我认为Timothy的方法是可行的,我用一个例子更新了我的答案,他使用您提供的例子实现。
    
    class C : I<char>
    {
        public char Value { get; set; }
        public Tuple<char, U> F<U>(U u)
        {
            return Tuple.Create(Value, u);
        }
    }
    
    I<char> instance = new C { Value = '!' };
    Tuple<char, int> x = instance.F(5); // ('!', 5)
    Tuple<char, string> y = instance.F("apple"); // ('!', "apple")
    
    interface ISieve<T>
    {
        //It's still not clear what you actually want in this interface...
    }
    
    static class Sieve
    {
        public EqualitySieve<T> Equality<T>()
        {
            return new EqualitySieve<T>();
        }
    
        public LessThanSieve<T> LessThan<T>()
        {
            ...
        }
    }    
    
    class EqualitySieve<T> : ISieve<T>
    {
        //Notice how the property type P is independent of T
        //and can be inferred here from the passed expression
        public EqualitySieve<T, P> ForProperty<P>(
            Expression<Func<T, P>> propertyExpression)
        {
            return new EqualitySieve<T, P>
            {
                PropertyExpression = propertyExpression
            };
        }
    }
    
    class EqualitySieve<T, P> : ISieve<T>
    {
        public Expression<Func<T, P>> PropertyExpression { get; set; }
    }
    
    //Assuming MyObject.MyProperty is an int property
    //s has type EqualitySieve<MyObject, int>
    var s = Sieve.Equality<MyObject>().ForProperty(x => x.MyProperty);