是否可以通用地实现此接口,以便只传递一个类型参数?

时间:2011-11-30 21:22:49

标签: c# .net generics .net-3.5

我有一个名为Identifiable<TId>的接口,它包含给定类型的单个属性Id。我想创建一个泛型类,将其中一个作为类型参数。它应该是通用的,因为我想返回具体类型,从其中调用其他泛型方法并使用typeof(T)之类的东西。

这很好用:

public class ClassName<T, TId> where T : Identifiable<TId>

问题是调用代码必须传递两种类型。例如。 new ClassName<Person, int>()

我想知道是否在.net 3.5中有一些方法可以写这个,以便可以用T推断TId?允许来电者只做new ClassName<Person>()

4 个答案:

答案 0 :(得分:2)

根据您问题的性质,我猜测您的ClassName并不依赖于Identifiable中需要TId的任何方法(否则您需要该类型。)如果是这样的话,在这种情况下,一个常见的解决方案是创建一个非通用的基本接口,所有方法都不需要TId类型。然后你有:

interface Identifiable<TId> : Identifiable //Not a standard interface name, btw

,您的约束变为:

public class ClassName<T> where T : Identifiable

假设您确实需要TId类型,但只是想简化构造语法,一个选项,如果您的构造函数采用Identifiable的实例(例如您的示例中的Person),则将构造函数更改为工厂方法:

public static ClassName<T, TId> FromIdentifiable<T,TId>(T identifiable) where T: Identifiable<TId>

上面应该允许编译器推断出类型,并根据参数的类型给出更短的语法。

答案 1 :(得分:1)

没有。您需要为Identifiable<>提供类型参数;如果不在类声明中声明参数,你怎么能这样做:

public class ClassName<T> where T : Identifiable<?WhatDoWePutHere?> 

答案 2 :(得分:1)

AFAIK,where子句无法实现。您可能希望使用代码合同(例如在.Net 4中)并添加

Contract.Requires(T is Identifiable<TId>);

代码。我不知道是否有任何方法可以在.Net 3.5中强制执行此操作。

答案 3 :(得分:1)

如果您的课程的大多数用途都是ClassName<Person, int>形式,其中T类型(人物)的大部分时间都不同,但TId类型几乎总是int,您可以提供部分解析的类,它提供TId类型但保持T类型不绑定。这样做的主要缺点是你将拥有多个必须具有不同名称的类。

public class BaseClassName<T, TId> where T: Identifiable<TId> 
{ }

public class ClassName<T> : ClassName<T, int> 
{ }

var x = new ClassName<Person>();

对于不希望int作为TId的情况较少的情况,那么arity 2类仍然可用:

var y = new BaseClassName<Person, int>()