您不能使用通用约束来表达您感兴趣的限制。泛型并不意味着表达基于不相交类型的变化 - 它们意味着表达在类型层次结构(或实现某些接口的类型)上统一的变化。
不过,您还有一些替代选择。您选择哪个取决于您想要做的事情的确切性质。
使用不同命名的方法来表达每个操作。当每种方法真正做不同的事情时,我倾向于使用这种方法。您可能会争辩说,从方法返回不同类型的值本质上是不同的操作,并且应该有自己独特的名称。
float GetFloat(string attrName) { }
string GetString(string attrName) { }
提供“默认值”以允许推断类型。在许多通过名称请求值的设计中,提供默认值很有用。这可以让您使用重载来区分要调用的方法(基于默认值的类型)。不幸的是,这种方法非常脆弱——并且在将文字值传递给接受数字基元(int、uint、long)的重载时很容易崩溃。
float GetValue(string attrName, float defaultValue) { ... }
string GetValue(string attrName, string defaultValue) { ... }
使用通用方法,但如果该类型不是您支持的类型之一,则抛出运行时异常。就我个人而言,我发现这种丑陋并且违反了泛型的精神 - 泛型应该统一层次结构或实现某些接口的一组类型的功能。但是,在某些情况下,这样做是有意义的(假设无法支持一种特定类型)。这种方法的另一个问题是,无法从任何参数推断泛型方法的签名,因此您必须在调用它时指定所需的类型......此时它并没有好多少(从语法的角度来看)而不是具有不同的方法名称。
T GetValue<T>( string attrName )
{
if( typeof(T) != typeof(string) ||
typeof(T) != typeof(float) )
throw new NotSupportedException();
return default(T);
}
// call it by specifying the type expected...
float f = GetValue<float>(attrName);
string s = GetValue<string>(attrName);
使用输出参数而不是返回值。这种方法效果很好,但它失去了能够调用方法并对返回值进行操作的简洁语法,因为您首先必须声明要填充的变量。
void GetValue( string attrName, out float value )
void GetValue( string attrName, out string value )
// example of usage:
float f;
GetValue( attrName, out f );
string s;
GetValue( attrName, out s );