Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “的实例在哪里?”;IntConverter";存储?_C#_.net_Expression Trees - Fatal编程技术网

C# “的实例在哪里?”;IntConverter";存储?

C# “的实例在哪里?”;IntConverter";存储?,c#,.net,expression-trees,C#,.net,Expression Trees,假设我们有以下程序: public class Program { private static Dictionary<Type, Func<object, object>> converters = new Dictionary<Type, Func<object[], object>>(); public static void Main(string[] args) { RegisterImplem

假设我们有以下程序:

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);
    }
}
公共类程序
{
私有静态字典转换器=新字典();
公共静态void Main(字符串[]args)
{
注册表实现(新的IntConverter());
int值=(int)dic[typeof(int)](“4”);
Console.WriteLine(值);//打印4
}
专用静态寄存器实现(IConverter转换器)
{
类型=类型(X);
Func conversion=(obj)=>converter.conversion(obj);
if(dic.ContainsKey(类型))
dic[类型]=转换;
其他的
添加(类型、转换);
}
}
公共接口IConverter
{
X转换(对象对象对象);
}
公共类IntConverter:IConverter
{
公共整数转换(对象obj)
{
返回转换为32(obj);
}
}
我理解大部分代码,但让我抓狂的部分是
RegisterImplementation
方法。在字典中,我们存储了一个
Func
实例,而
converter
没有存储在任何地方,因此我假设当我们离开该方法时,我们会丢失本地引用


那么,我们以后如何调用字典中的函数并使用
IntConverter
的引用呢?它存放在哪里?在
Func

内部,lambda代码
(obj)=>转换器。Convert(obj)
使用本地
转换器。这个lambda代码使本地保持活动状态。

首先,值得一提的是,您的问题实际上根本不涉及表达式树-您的lambda表达式只是被转换为一个委托

现在,lambda表达式是这样的:

(obj) => converter.Convert(obj)
它捕获局部变量,
converter
。实际上,这意味着C#编译器将创建一个新类,如下所示:

private class UnspeakableName<X>
{
    public IConverter<X> converter;

    public object Method(object obj)
    {
        return converter(obj);
    }
}
私有类无法说出的名称
{
公共i转换器;
公共对象方法(对象obj)
{
返回转换器(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);
}
专用静态寄存器实现(IConverter转换器)
{
UnspeakableName tmp=新的UnspeakableName();
tmp.converter=转换器;
类型=类型(X);
Func conversion=tmp.方法;
if(dic.ContainsKey(类型))
dic[类型]=转换;
其他的
添加(类型、转换);
}

因此,委托的目标将是新类的实例,这将使转换器保持活动状态。

请参阅,尤其是“Lambda表达式中的变量作用域”一节:“以这种方式捕获的变量将存储起来,以便在Lambda表达式中使用,即使变量会超出作用域。”还有谁觉得有必要读一本乔恩的书吗?谢谢你完美的解释