我有一个通用方法$creds = Get-Credential
$unsecureCreds = $creds.GetNetworkCredential()
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $unsecureCreds.UserName,$unsecureCreds.Password)))
Remove-Variable unsecureCreds
Invoke-RestMethod -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} ...
。
在方法内部,我需要根据T的实际类型采取具体行动:
public void DoAThing<T>(T inputData)
当我想出更多类型的动作时,如何保持if / else语句不断增长?用if (typeof(T) == int)
{
// Handle integer input.
}
else if (typeof(T) == string)
{
// Do something else.
}
else
{
// Default action.
}
语句替换在语法上看起来更好,但是具有相同的底层问题:我必须添加越来越多的案例。
直觉上我明白切换必须在某个时刻完成,我只是在寻找一种更优雅的方式。
编辑:我得到的答案并不是我想要的,但这可能是因为我走错了路。我意识到我的原始问题已经解决,这可能是问题的一部分。
与我合作的方法实际上是:
switch
因此,我打开T的原因是因为该方法需要进行一些不同的处理才能获得返回值。在这种情况下,什么更有效:对每个预期类型使用if / else的泛型方法,或者只为每个有效返回类型使用一系列方法(public T void ReturnAThing<T>(string thingName)
,ReturnAString
等等)?
答案 0 :(得分:0)
或许(或许强调)你想要的是这样的东西。 (最后这个长期答案的底部解释了为什么你不应该这样做。但实验起来不错。)
public abstract class DoesSomething<T>
{
public abstract void DoSomething(T input);
}
现在,您可以编写针对特定类型覆盖此内容的单个类:
public class DoesSomethingWithAString : DoesSomething<string>
{
public override void DoSomething(string input)
{
// Do whatever
}
}
正如评论中所提到的,如果您正在检查某些内容以查看其类型,则会出现问题。类型安全的一个好处是您只需要知道对象的声明类型。即使实际实例是从该声明类型继承的东西,您也不需要知道。如果参数显示为Foo
,那么它就是Foo
,这就是您需要知道的全部内容。
如果我们必须检查对象以确定它们的类型,那么一切都可能只是object
,如下所示:
public class DoesSomething
{
public void DoSomething(object input)
{
if(input is string)
{
// Do something
}
if(input is Foo)
{
// Do something
}
}
}
当泛型类没有“关心”时,泛型是有意义的。具体类型是什么,如List<T>
。无论T
是什么,它都会保留T
的实例。或者您可以对其进行约束,如:
public class MyFooHandler<TFoo> where TFoo:Foo
确保泛型类型为Foo
或继承自Foo
。但在这种情况下,这些方法应该只关心&#34;它是Foo
。如果你发现自己正在检查它是什么样的Foo
,那么又出现了一些问题。
如果您的某个班级可能在int
上运行,或者可能在string
上运行,那么一个好问题是,为什么它需要是一个班级或一个方法,因为它可能会做两件完全不同的事情?也许应该有两个班级。也许应该有一个有多种方法的类。也许您只需要string
方法,并且在调用方法之前应将您的整数转换为字符串。
有时候我们会被这些问题所吸引,因为我们正试图想办法让一个班级做很多不同的事情。当我们尝试使用泛型时,这种情况会发生很多。但通常答案是,如果我们做两件不同的事情,我们应该有两个班级。
即使在上面两个类继承自DoesSomething<T>
的示例中,也很有问题,让这些类从一个基类继承有什么好处?通常没有任何好处,它只会在以后制造麻烦。最好开始写个别的课程,每个课程做一件小事或一些密切相关的小事。
答案 1 :(得分:0)
你应该这样做
public void DoAThing(int inputData)
public void DoAThing(string inputData)
答案 2 :(得分:0)
通过使用单一泛型方法,您允许调用者从中获得任何类型的返回值,但是您可以在方法中处理它吗?
此示例显示您可以轻松破坏能够处理任何返回类型的方法契约:
@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
}
我认为你这里只有两个选择:
1)让您的方法获取Class实例,以便您可以知道调用者期望的返回类型。 ˚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
}
2)为每种返回类型设置单独的方法。
哪种方法对你更好?这取决于。如果您正在处理少数不同的返回类型,那么请使用单独的方法方法。