C# 如何简化泛型方法中的条件?

C# 如何简化泛型方法中的条件?,c#,generics,C#,Generics,我有一个通用方法public void DoAThing(T inputData) 在方法中,我需要根据T的实际类型采取具体措施: if (typeof(T) == int) { // Handle integer input. } else if (typeof(T) == string) { // Do something else. } else { // Default action. } 当我为更多类型提出操作时,如何防止if/else语句变得任意大?替换为switch语

我有一个通用方法
public void DoAThing(T inputData)

在方法中,我需要根据T的实际类型采取具体措施:

if (typeof(T) == int)
{
  // Handle integer input.
}
else if (typeof(T) == string)
{
  // Do something else.
}
else
{
  // Default action.
}
当我为更多类型提出操作时,如何防止if/else语句变得任意大?替换为
switch
语句在语法上看起来更好,但有相同的潜在问题:我必须添加越来越多的案例

直觉上,我知道转换必须在某个时候完成,我只是在寻找一种更优雅的方式

编辑:我得到的答案并不完全是我想要的,但这可能是因为我走错了路。我意识到我原来的问题是错的,这可能是问题的一部分

我使用的方法实际上是:

public T void ReturnAThing(字符串名称)

因此,我之所以启用T,是因为该方法需要进行一些不同的处理以获得返回值。在这种情况下,什么更有效:对每个预期类型使用带有if/else的泛型方法,或者对每个有效的返回类型使用一系列方法(
ReturnAString
returnanit
,等等)?

也许(强调也许)您想要的是这样的。(最终,这个长答案的底部解释了为什么你不应该这样做。但这是一个很好的实验。)

当泛型类不“关心”特定类型是什么时,泛型是有意义的,比如
List
。它将保存
T
的实例,而不管
T
是什么。或者您可以对其设置一个约束,如:

public class MyFooHandler<TFoo> where TFoo:Foo
公共类myfoodhandler,其中TFoo:Foo
这确保泛型类型为
Foo
或继承自
Foo
。但是在这种情况下,这些方法应该只“注意”它是一个
Foo
。如果您发现自己在检查它,看看它是什么类型的
Foo
,那么再次说明,出了问题

如果您有一个类可能在
int
上操作,或者可能在
字符串上操作,那么一个好问题是,既然它可能在做两件完全不同的事情,为什么它需要一个类或一个方法?也许应该有两门课。也许应该有一个类具有多个方法。也许您只需要一个
string
方法,在调用该方法之前,您的int应该转换为string

有时我们会被这些问题所吸引,因为我们试图找到一种方法让一个类做很多不同的事情。当我们在实验泛型时,这种情况经常发生。但答案往往是,如果我们在做两件不同的事情,我们应该有两门课

即使在上面的示例中,有两个类继承自
doesmething
,我们也可以问,让这些类继承自一个基类有什么好处?很多时候,这根本没有任何好处,只是在以后制造麻烦。最好从编写单独的类开始,每个类都做一件小事或几个密切相关的小事。

你应该做的事

public void DoAThing(int inputData)

public void DoAThing(string inputData)

通过使用单个泛型方法,您允许调用方期望从中得到任何类型的返回值,但是您能在方法中处理它吗

此示例显示,您可以轻松打破能够处理任何返回类型的方法契约:

@SuppressWarnings("unchecked")
public <T> T returnAThing(String input){
    if (input.equals("a") ) return (T) new Integer(1);
    else if (input.equals("b") ) return (T)"ABC";
    else return null;
}    

@Test
public void test(){
  Integer result1 = returnAThing("a"); //ok result is 1
  Integer result2 = returnAThing("b"); //fails      
}
@SuppressWarnings(“未选中”)
公共T返回(字符串输入){
if(input.equals(“a”))返回(T)个新整数(1);
否则如果(输入等于(“b”)返回(T)“ABC”;
否则返回null;
}    
@试验
公开无效测试(){
整数result1=returnAThing(“a”);//确定结果为1
整数result2=returnAThing(“b”);//失败
}
我想你只有两个选择:

1) 让您的方法获取类实例,这样您就可以知道调用者希望从您那里得到什么样的返回类型。F

@SuppressWarnings("unchecked")
public <T> T returnAThing(Class<T> type, String input){
    if ( input.equals("a") && type.equals(Integer.class) ) return (T) new Integer(1);
    else if (input.equals("b") && type.equals(String.class) ) return (T)"ABC";
    else return null;
}    

@Test
public void test(){
  Integer result = returnAThing(Integer.class, "a");  //ok result is 1      
  result = returnAThing(Integer.class, "b"); //ok result is null
}
@SuppressWarnings(“未选中”)
公共T返回(类类型,字符串输入){
if(input.equals(“a”)&&type.equals(Integer.class))返回(T)个新整数(1);
else if(input.equals(“b”)&type.equals(String.class))返回(T)“ABC”;
否则返回null;
}    
@试验
公开无效测试(){
整数结果=returnAThing(Integer.class,“a”);//确定结果为1
result=returnAThing(Integer.class,“b”);//确定结果为空
}
2) 每个返回类型都有单独的方法



哪种方法更适合你?视情况而定。如果你处理的是少数几种不同的返回类型,那么就使用单独的方法。

直觉上,我理解必须在某个时候进行切换
不,事实上,如果你在切换类型,你就犯了很大的错误。如果要为三种不同类型的参数执行三种不同的操作,则参数有三种不同的重载,并且没有开关。通用方法应该是通用的;你的方法实际上不是泛型的。
public void DoAThing(int inputData)

public void DoAThing(string inputData)
@SuppressWarnings("unchecked")
public <T> T returnAThing(String input){
    if (input.equals("a") ) return (T) new Integer(1);
    else if (input.equals("b") ) return (T)"ABC";
    else return null;
}    

@Test
public void test(){
  Integer result1 = returnAThing("a"); //ok result is 1
  Integer result2 = returnAThing("b"); //fails      
}
@SuppressWarnings("unchecked")
public <T> T returnAThing(Class<T> type, String input){
    if ( input.equals("a") && type.equals(Integer.class) ) return (T) new Integer(1);
    else if (input.equals("b") && type.equals(String.class) ) return (T)"ABC";
    else return null;
}    

@Test
public void test(){
  Integer result = returnAThing(Integer.class, "a");  //ok result is 1      
  result = returnAThing(Integer.class, "b"); //ok result is null
}