强制泛型类型参数

时间:2012-09-25 10:24:55

标签: c# .net generics types

我正在为.NET构建一个HTTP-API包装器,它有一堆方法来设置对象中的数据,然后它将数据序列化并发送到我的服务器。允许使用6种数据类型:

  • 字符串
  • INT
  • 日期时间

我的数据属性使用泛型:

SetAttribute<T>(string key, T value)

因此,只有一种通用方法可以设置数据。由于我不能将数据类型约束到上面提到的6,我使用运行时检查并在使用错误的数据类型时抛出异常。

现在我的问题是:我有两个版本的SetAttribute,一个采用单个值(类型为T),另一个采用多个值(类型为IEnumerable&lt; T&gt;)。问题在于,当程序员使用此包装器并且未指定type参数时,运行时会猜测要使用的方法,例如:

SetAttribute("testkey","thing,anotherthing,athirdthing".Split(','))

这默认为单值方法,T是String [],这当然使我的方法转换为异常,因为String []不是有效类型。如果您指定:

SetAttribute<string>("testkey","thing,anotherThing,aThirdThing".Split(','))

运行时选择正确的方法(多值)并且不会抛出异常,因为T就是字符串。

我的问题:如何标记我的方法,以便类型参数是必需的,必须明确定义?或者我是否必须在运行时检测到这一点并自行重定向到多方法?

4 个答案:

答案 0 :(得分:2)

给定参数类型,编译器会从重载中找到最佳匹配。如果您将string[]转换为IEnumerable<string>,您可能会发现它按预期工作,因为最佳匹配是具有这些参数的方法。但是你没有采用string[]的方法,所以给定一个作为参数,编译器可以做出最好的猜测。

我会有两个单独命名的方法而不是重载,否则很容易遇到这个问题。或者有6个独立的重载,正如@Joachim建议的那样。

答案 1 :(得分:2)

好的,这最初是上面的评论,因为它不一定能回答你原来的问题,但提出了另一种方法;

我想说在这种情况下使用公共泛型 SetAttribute并不是一个好主意。

由于类型受到限制,您应该只编写重载并将错误从运行时移动到编译时。它还允许您将IEnumerable<string>等用于另外6次重载,并消除您完全拥有的问题。

您始终可以使用私有泛型实现SetAttribute,并且只需从每个重载调用它,这将删除一些重复。

它也或多或少地消除了对运行时检查的需要,因为类型已经被编译器约束。

答案 2 :(得分:0)

一种解决方案是将原始方法分解为6个非泛型重载,并为集合添加另一个泛型重载:

void SetAttribute(string key, int value);
void SetAttribute(string key, string value);
// etc

// abd this takes care of collections:
void SetAttribute<T>(string key, IEnumerable<T> value);

答案 3 :(得分:0)

我建议一个更好的解决方案是测试传入的值是否在IEnumerable失败之后是其他所有内容并将其视为如此。 (我想你已经将IEnumerable作为第七种情况处理了。)