考虑以下(大大简化的)代码:
public T Function<T>() {
if (typeof(T) == typeof(string)) {
return (T) (object) "hello";
}
...
}
在先将类型转换为object,然后转换为T的过程中,似乎有点荒谬。但是编译器并不知道之前的测试已经保证了T是字符串类型。在C#中,最优雅和惯用的方法是什么(包括摆脱愚蠢的typeof(T) == typeof(string),因为不能使用T is string)?
附:.net没有返回类型差异,因此无法创建以字符串类型重载的函数(例如,这只是一个例子,但这也是多态性中关联端重新定义(例如UML)不能在C#中完成的原因之一)。显然,下面的方法很好,但它不起作用。
public T Function<T>() {
...
}
public string Function<string>() {
return "hello";
}
具体例子1:由于有人曾经质疑测试特定类型的通用函数不是通用的,因此我将尝试提供一个更完整的示例。考虑Type-Square设计模式,以下是代码片段:
public class Entity {
Dictionary<PropertyType, object> properties;
public T GetTypedProperty<T>(PropertyType p) {
var val = properties[p];
if (typeof(T) == typeof(string) {
(T) (object) p.ToString(this); // magic going here
}
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(val);
}
}
具体例子2:考虑解释器设计模式:
public class Expression {
public virtual object Execute() { }
}
public class StringExpression: Expression {
public override string Execute() { } // Error! Type variance not allowed...
}
现在让我们在Execute中使用泛型,以允许调用者强制返回类型:
public class Expression {
public virtual T Execute<T>() {
if(typeof(T) == typeof(string)) { // what happens when I want a string result from a non-string expression?
return (T) (object) do_some_magic_and_return_a_string();
} else if(typeof(T) == typeof(bool)) { // what about bools? any number != 0 should be True. Non-empty lists should be True. Not null should be True
return (T) (object) do_some_magic_and_return_a_bool();
}
}
}
public class StringExpression: Expressiong {
public override T Execute<T>() where T: string {
return (T) string_result;
}
}
Evaluate<T>
,它映射DSL的AST。底层语言是动态类型的,因此调用者不会事先知道确切的类型Evaluate<T>
。但是,如果调用者强制指定一个特定类型,例如Evaluate<bool>
,则该函数可以添加一些“语义糖果”,例如测试null、大于0的数字、非空列表等。无论发生什么,调用者都期望得到一个bool
。 - Hugo Sereno Ferreirabool
之间的显式转换中。但想象一下,添加的“语义糖”取决于评估上下文。那么,在显式转换中存储逻辑将需要对象仅为此目的存储足够的信息。 - Hugo Sereno Ferreira