我可以忽略C#接口中的泛型类型吗? 背景
我正在着手一个叫做OSS的小程序库 签名允许某人定义一个我可以忽略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); 这实际上返回了一个筛选,但我已经尽了最大努力确保用户不必太在意这一部分 任务 我想找到一种方法,在这里放置一个接口,我根本不关心属性类型——只是它始终是一致的 因此,本质上,我希望能够声明
筛
,如下所示:
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);
@Scott谢谢你抓住了这些打字错误。@ScottChamberlain说得好。我认为我没有恰当地说明我的目标,而是把重点放在一个技术问题上,而这个问题可能是一个设计问题。我要重新措辞。不幸的是,我要跳上一个航班,所以它可能需要等待一段时间。这取决于他所说的“一致性”,如果他是说“多个函数都使用相同的类型”,这将不起作用,但如果他是说“此函数中此变量的使用是一致的”,那么这将非常有效。@Timothy,感谢您的回复!抱歉等了这么久;我补充了一些澄清,希望对我的意图有所帮助。请让我知道任何我能澄清的事情。我感谢您的帮助。@SeanKilleen请查看我的更新,并告诉我是否更接近了。@TimothyShields肯定越来越接近了。我正在研究一个要点,以展示我现在要看的内容是否更有意义。本质上,我希望能够编写一些能够找到//假设MyObject.MyProperty是int属性 //s型平衡筛 var s=Sieve.Equality().ForProperty(x=>x.MyProperty);
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);
- 我允许用户创建