C# 访问匿名操作委托中类的局部变量

C# 访问匿名操作委托中类的局部变量,c#,.net,delegates,anonymous-function,C#,.net,Delegates,Anonymous Function,当委托是匿名的,并且包含的类作为函数的参数及时创建时,我很难理解如何访问操作委托中的局部类变量 委托似乎可以访问调用函数变量,并且它包含类,但不能访问实际包含委托的类。如果我不清楚我的问题,请原谅,我正在尽我最大的努力表达。请参考以下代码: public class QueryPropertyMessage { public Action Callback { get; private set; } public string PropertyName { get; set; }

当委托是匿名的,并且包含的类作为函数的参数及时创建时,我很难理解如何访问操作委托中的局部类变量

委托似乎可以访问调用函数变量,并且它包含类,但不能访问实际包含委托的类。如果我不清楚我的问题,请原谅,我正在尽我最大的努力表达。请参考以下代码:

public class QueryPropertyMessage
{
    public Action Callback { get; private set; }
    public string PropertyName { get; set; }
    public object PropertyValue { get; set; }

    public QueryPropertyMessage(Action callback)
    {
        this.Callback = callback;
    }

}

Class TestClass
{
    public void OuterTestFunction()
    {
        //the function will set PeropertyValue
        SomeClass.FunctionAcceptingQueryPropertyMessageObject (new QueryPropertyMessage (() =>
        {
            Helper.DebugHelper.TraceMessage ("Test Anonymous method");
            //Error The name 'PropertyValue' does not exist in the current context
            If(PropertyValue!=null)
                var val = Convert.ChangeType (PeropertyValue, typeof (bool));
        }) { PropertyName = "SomeBooleanProperty" });
    }
}
如何访问匿名委托中QueryPropertyMessage对象的属性?
在阅读匿名方法时,我似乎认为委托将被包装在另一个helper类中,因此从委托的角度来看,看起来包含类(QueryPropertyMessage)的不是本地类。我希望能更清楚地理解它。

这样做有点痛苦。基本上,您需要声明一个局部变量,给它一个临时值(以便它被明确赋值),然后使用该局部变量:

QueryPropertyMessage message = null;
message = new QueryPropertyMessage(() =>
{
    // Use message in here
});
SomeClass.FunctionAcceptingQueryPropertyMessageObject(message);
QueryPropertyMessage message = null;

message = new QueryPropertyMessage(() =>
    {
        var propertyName = message.PropertyName;
    });
这取决于构造函数中没有调用回调-否则它将看到
消息的原始
null


(当然,您也可以更改回调以接收消息。)

这样做有些痛苦。基本上,您需要声明一个局部变量,给它一个临时值(以便它被明确赋值),然后使用该局部变量:

QueryPropertyMessage message = null;
message = new QueryPropertyMessage(() =>
{
    // Use message in here
});
SomeClass.FunctionAcceptingQueryPropertyMessageObject(message);
QueryPropertyMessage message = null;

message = new QueryPropertyMessage(() =>
    {
        var propertyName = message.PropertyName;
    });
这取决于构造函数中没有调用回调-否则它将看到
消息的原始
null


(当然,您也可以更改回调以接收消息。)

需要在创建或甚至定义
QueryPropertyMessage
之前创建操作,以便您能够将其传递到其构造函数中。因此,在当时没有什么可供参考的。您需要首先为所讨论的对象创建或至少定义一个变量

QueryPropertyMessage message = new QueryPropertyMessage();
message.Callback = () =>
{
    var propertyName = message.PropertyName;
};
(这当然需要为回调提供一个无参数构造函数和一个setter。)

如果不想修改该类,则只能定义变量,而不能初始化变量:

QueryPropertyMessage message = null;
message = new QueryPropertyMessage(() =>
{
    // Use message in here
});
SomeClass.FunctionAcceptingQueryPropertyMessageObject(message);
QueryPropertyMessage message = null;

message = new QueryPropertyMessage(() =>
    {
        var propertyName = message.PropertyName;
    });
或者您需要将对象本身作为参数传递给操作:

public class QueryPropertyMessage
{
    public Action<QueryPropertyMessage> Callback { get; private set; }
    public string PropertyName { get; set; }
    public object PropertyValue { get; set; }

    public QueryPropertyMessage(Action<QueryPropertyMessage> callback)
    {
        this.Callback = callback;
    }
}

需要在创建或甚至定义
QueryPropertyMessage
之前创建操作,以便您能够将其传递到其构造函数中。因此,在当时没有什么可供参考的。您需要首先为所讨论的对象创建或至少定义一个变量

QueryPropertyMessage message = new QueryPropertyMessage();
message.Callback = () =>
{
    var propertyName = message.PropertyName;
};
(这当然需要为回调提供一个无参数构造函数和一个setter。)

如果不想修改该类,则只能定义变量,而不能初始化变量:

QueryPropertyMessage message = null;
message = new QueryPropertyMessage(() =>
{
    // Use message in here
});
SomeClass.FunctionAcceptingQueryPropertyMessageObject(message);
QueryPropertyMessage message = null;

message = new QueryPropertyMessage(() =>
    {
        var propertyName = message.PropertyName;
    });
或者您需要将对象本身作为参数传递给操作:

public class QueryPropertyMessage
{
    public Action<QueryPropertyMessage> Callback { get; private set; }
    public string PropertyName { get; set; }
    public object PropertyValue { get; set; }

    public QueryPropertyMessage(Action<QueryPropertyMessage> callback)
    {
        this.Callback = callback;
    }
}

你不能那样做。委托不知道它正在被传递给构造函数。这就像一个
int
知道包含它的类型一样

解决此问题的一种方法是公开setter,创建
QueryPropertyMessage
的实例,然后设置委托

var query = new QueryPropertyMessage();

query.Callback = () =>
        {
            Helper.DebugHelper.TraceMessage ("Test Anonymous method");
            If(query.PropertyValue!=null)
                var val = Convert.ChangeType (PeropertyValue, typeof (bool));
        };
这样,lambda将关闭您的
QueryPropertyMessage
实例并访问它

我似乎认为委托将被包装在另一个helper类中

仅当它需要关闭(查找闭包)一个或多个变量时。在上面的代码中,这将发生

编译器将创建一个类,该类将您的
QueryPropertyMessage
实例作为字段,并创建一个实现lambda的方法,如下所示:

public class <Lambda>b__0
{
    private readonly QueryPropertyMessage _query = ...

    public void Execute()
    {
        Helper.DebugHelper.TraceMessage ("Test Anonymous method");
        If(_query.PropertyValue!=null)
            var val = Convert.ChangeType (PeropertyValue, typeof (bool));
    }
}
公共b类0
{
私有只读QueryPropertyMessage\u查询=。。。
public void Execute()
{
Helper.DebugHelper.TraceMessage(“测试匿名方法”);
If(_query.PropertyValue!=null)
var val=Convert.ChangeType(peroperyValue,typeof(bool));
}
}

你不能那样做。委托不知道它正在被传递给构造函数。这就像一个
int
知道包含它的类型一样

解决此问题的一种方法是公开setter,创建
QueryPropertyMessage
的实例,然后设置委托

var query = new QueryPropertyMessage();

query.Callback = () =>
        {
            Helper.DebugHelper.TraceMessage ("Test Anonymous method");
            If(query.PropertyValue!=null)
                var val = Convert.ChangeType (PeropertyValue, typeof (bool));
        };
这样,lambda将关闭您的
QueryPropertyMessage
实例并访问它

我似乎认为委托将被包装在另一个helper类中

仅当它需要关闭(查找闭包)一个或多个变量时。在上面的代码中,这将发生

编译器将创建一个类,该类将您的
QueryPropertyMessage
实例作为字段,并创建一个实现lambda的方法,如下所示:

public class <Lambda>b__0
{
    private readonly QueryPropertyMessage _query = ...

    public void Execute()
    {
        Helper.DebugHelper.TraceMessage ("Test Anonymous method");
        If(_query.PropertyValue!=null)
            var val = Convert.ChangeType (PeropertyValue, typeof (bool));
    }
}
公共b类0
{
私有只读QueryPropertyMessage\u查询=。。。
public void Execute()
{
Helper.DebugHelper.TraceMessage(“测试匿名方法”);
If(_query.PropertyValue!=null)
var val=Convert.ChangeType(peroperyValue,typeof(bool));
}
}

问题的解决方案是您需要将操作类型更改为
操作
回调

class QueryPropertyMessage
{
    public Action<QueryPropertyMessage> Callback { get; private set; }
    public string PropertyName { get; set; }
    public object PropertyValue { get; set; }

    public QueryPropertyMessage(Action<QueryPropertyMessage> callback)
    {
        this.Callback = callback;
    }

}

public class TestClass
{
    public void OuterTestFunction()
    {

        //the function will set PeropertyValue
        SomeClass.FunctionAcceptingQueryPropertyMessageObject (new QueryPropertyMessage ((item) =>
        {
            Helper.DebugHelper.TraceMessage ("Test Anonymous method");
            //Error The name 'PropertyValue' does not exist in the current context
            If(item.PropertyValue!=null)
                var val = Convert.ChangeType (PeropertyValue, typeof (bool));
        }) { PropertyName = "SomeBooleanProperty" });
    }
}
}
类查询属性消息
{
公共操作回调{get;private set;}
公共字符串PropertyName{get;set;}
公共对象属性值{get;set;}
公共查询属性消息(操作回调)
{
this.Callback=Callback;
}
}
公共类TestClass
{
public void OuterTestFunction()
{
//该函数将设置PeroperyValue
SomeClass.FunctionAcceptingQueryPropertyMessageObject(新的QueryPropertyMessage((项)=>
{
Helper.DebugHelper.TraceMessage(“测试匿名方法”);
//错误当前上下文中不存在名称“PropertyValue”