"IntConverter" 的实例存储在哪里?
Where is the instance of "IntConverter" stored?
假设我们有以下程序:
public class Program
{
private static Dictionary<Type, Func<object, object>> converters = new Dictionary<Type, Func<object[], object>>();
public static void Main(string[] args)
{
RegisterImplementation(new IntConverter());
int value = (int) dic[typeof(int)]("4");
Console.WriteLine(value); //Prints 4
}
private static RegisterImplementation<X>(IConverter<X> converter)
{
Type type = typeof(X);
Func<object, object> conversion = (obj) => converter.Convert(obj);
if(dic.ContainsKey(type))
dic[type] = conversion;
else
dic.Add(type, conversion);
}
}
public interface IConverter<X>
{
X Convert(object obj);
}
public class IntConverter : IConverter<int>
{
public int Convert(object obj)
{
return Convert.ToInt32(obj);
}
}
我理解大部分代码,但让我抓狂的部分是 RegisterImplementation
方法。在字典中我们存储了一个 Func<object, object>
实例,而 converter
没有存储在任何地方,所以我假设我们在退出方法时丢失了本地引用。
那以后怎么调用字典里的函数,用这个IntConverter
的引用呢?它存储在哪里? Func<object, object>
?
里面
lambda 代码 (obj) => converter.Convert(obj)
使用本地 converter
。这个 lambda 代码使本地保持活动状态。
首先,值得明确的是,您的问题实际上根本不涉及表达式树 - 您的 lambda 表达式只是被转换为委托。
现在,lambda 表达式是这样的:
(obj) => converter.Convert(obj)
捕获局部变量,converter
。实际上,这意味着 C# 编译器将创建一个新的 class,如下所示:
private class UnspeakableName<X>
{
public IConverter<X> converter;
public object Method(object obj)
{
return converter(obj);
}
}
那么你的方法将被转换成:
private static RegisterImplementation<X>(IConverter<X> converter)
{
UnspeakableName<X> tmp = new UnspeakableName<X>();
tmp.converter = converter;
Type type = typeof(X);
Func<object, object> conversion = tmp.Method;
if(dic.ContainsKey(type))
dic[type] = conversion;
else
dic.Add(type, conversion);
}
因此委托的目标将是新 class 的实例,并且 使转换器保持活动状态。
假设我们有以下程序:
public class Program
{
private static Dictionary<Type, Func<object, object>> converters = new Dictionary<Type, Func<object[], object>>();
public static void Main(string[] args)
{
RegisterImplementation(new IntConverter());
int value = (int) dic[typeof(int)]("4");
Console.WriteLine(value); //Prints 4
}
private static RegisterImplementation<X>(IConverter<X> converter)
{
Type type = typeof(X);
Func<object, object> conversion = (obj) => converter.Convert(obj);
if(dic.ContainsKey(type))
dic[type] = conversion;
else
dic.Add(type, conversion);
}
}
public interface IConverter<X>
{
X Convert(object obj);
}
public class IntConverter : IConverter<int>
{
public int Convert(object obj)
{
return Convert.ToInt32(obj);
}
}
我理解大部分代码,但让我抓狂的部分是 RegisterImplementation
方法。在字典中我们存储了一个 Func<object, object>
实例,而 converter
没有存储在任何地方,所以我假设我们在退出方法时丢失了本地引用。
那以后怎么调用字典里的函数,用这个IntConverter
的引用呢?它存储在哪里? Func<object, object>
?
lambda 代码 (obj) => converter.Convert(obj)
使用本地 converter
。这个 lambda 代码使本地保持活动状态。
首先,值得明确的是,您的问题实际上根本不涉及表达式树 - 您的 lambda 表达式只是被转换为委托。
现在,lambda 表达式是这样的:
(obj) => converter.Convert(obj)
捕获局部变量,converter
。实际上,这意味着 C# 编译器将创建一个新的 class,如下所示:
private class UnspeakableName<X>
{
public IConverter<X> converter;
public object Method(object obj)
{
return converter(obj);
}
}
那么你的方法将被转换成:
private static RegisterImplementation<X>(IConverter<X> converter)
{
UnspeakableName<X> tmp = new UnspeakableName<X>();
tmp.converter = converter;
Type type = typeof(X);
Func<object, object> conversion = tmp.Method;
if(dic.ContainsKey(type))
dic[type] = conversion;
else
dic.Add(type, conversion);
}
因此委托的目标将是新 class 的实例,并且 使转换器保持活动状态。