【发布时间】:2013-05-30 05:12:55
【问题描述】:
我正在编写一个泛型方法,我希望根据泛型 Type 参数的类型出现不同的执行路径。不同的执行路径是静态类型的,例如
public static T Get<T>(this NameValueCollection collection, string name) where T : struct
{
//Perform test on type, if it matches, delegate to statically typed method.
if (typeof(T) == typeof(int)) return (T)(object)GetInt32(collection, name);
else if (typeof(T) == typeof(DateTime)) return (T) (object) GetDateTime(collection, name);
//Other types parsed here...
//If nothing matched, return default.
return default(T);
}
我发现能够使用静态执行路径的返回结果的唯一方法是将其装箱为对象,然后将其强制转换为'T'。
对我来说,这首先违背了使用泛型方法的目的(除了获得一些语法糖)。在我们已经确定 T 是 int 类型的情况下,有谁知道一种能够将 int 值返回为 T 的方法?
我正在考虑使用“动态”类型的 var,但读到它只是在幕后使用对象结束。
这大概是泛型的范围吗?
--
根据 smartcaveman 的回复更新以包含我的最终方法,该方法使用通用静态类的类型解析来确定使用哪种“解析”方法,无需装箱或使用动态。
public class StringParser
{
private class Getter<T>
{
private static readonly ConcurrentDictionary<StringParser, Getter<T>> Getters = new ConcurrentDictionary<StringParser, Getter<T>>();
public Func<string, T> Get { get; set; }
private Getter() {}
public static Getter<T> For(StringParser stringParser)
{
return Getters.GetOrAdd(stringParser, x => new Getter<T>());
}
}
public virtual T Get<T>(string value)
{
var get = Getter<T>.For(this).Get;
if (get == null) throw new InvalidOperationException(string.Format("No 'get' has been configured for values of type '{0}'.", typeof (T).Name));
return get(value);
}
public void SetupGet<T>(Func<string, T> get)
{
Getter<T>.For(this).Get = get;
}
}
使用相当简单:
public static void Usage()
{
StringParser parser = new StringParser();
parser.SetupGet(Int32.Parse);
int myInt = parser.Get<int>("3");
}
smartcaveman方法的诡计在于,具有不同类型参数的泛型静态类实际上被认为是不同的类型,并且不共享静态成员。
非常酷的东西,谢谢!
【问题讨论】:
-
请注意区别,在我的示例中,对 Configure 的调用是静态的并且是全局应用的。这会减少代码,并意味着您不必为每个实例设置每个解析器。但是,它基于一个假设,即实例不会在不同的上下文中以不同的方式解析相同的值类型(这可能适用于您的用例,也可能不适用)。一个理想的解决方案可能是混合的:它会默认为本地(实例范围)配置,首先回退到全局/静态配置,作为最后的手段,回退到 default(T)。
-
@nawfal,类似,解决关键核心原则(泛型类型推断),但我认为我的问题来自不同的用例,我们不是将泛型类型转换为已知类型,而是将已知类型(字符串)重新转换为任意泛型类型(T)。
-
@Martaver 哦,是的,我错过了通用部分。