这个接口可不可以通用实现,只需要传入一个类型参数就可以了?

5

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

这可以正常工作:

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

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

我想知道在 .net 3.5 中是否有一种方法可以编写代码,使得 TId 可以由 T 推断出来?这样调用者只需要使用 new ClassName<Person>() 就行了吗?


1
也许您可以展示一个稍微详细些的例子,这样就能清楚地看出您想要做什么以及为什么。 - deepee1
4个回答

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

不行。你需要为 Identifiable<> 提供一个类型参数;如果没有在类声明中声明该参数,你怎么能做到呢:

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

1
据我所知,在where子句中不可能实现。您可能需要使用代码合同(例如在.Net 4中)并添加。
Contract.Requires(T is Identifiable<TId>);

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


1
如果你的类大多数使用形式为ClassName<Person, int>,其中T类型(Person)大多数情况下是变化最大的,但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时,仍然可以使用二元类:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接