C#用委托构造不可变对象

C#用委托构造不可变对象,c#,delegates,closures,immutability,factory-pattern,C#,Delegates,Closures,Immutability,Factory Pattern,我正在尝试设计一个工厂类,使我的团队中的人员能够轻松地添加新的“操作”,我希望该类的属性是不可变的,但出于调试目的,我希望代理能够引用包含该类的属性 考虑以下类别: public class NamedAction { public NamedAction(string name, Action action) { // Here there is some additional validation, // such as null param

我正在尝试设计一个工厂类,使我的团队中的人员能够轻松地添加新的“操作”,我希望该类的属性是不可变的,但出于调试目的,我希望代理能够引用包含该类的属性

考虑以下类别:

public class NamedAction
{
    public NamedAction(string name, Action action)
    {
        // Here there is some additional validation, 
        // such as null parameter checking, etc.
        Name = name;
        Action = action;
    }

    public string Name { get; private set; }

    public Action Action { get; private set; }

    public override string ToString()
    {
      return "Action: " + Name;
    }
}
在factory类中,我使用以下方法创建特殊命名操作的实例:

private static NamedAction GetSpecialAction()
{
    NamedAction na = null;
    na = new NamedAction(
        "SpecialAction",
        () => {
            Console.WriteLine("My name is " + na.Name + " and I am special");
            Console.WriteLine("Hi, its " + na.Name + " again. I like kittens.");
        }
    );
    return na;
}
我的问题是ReSharper告诉我第二个Console.WriteLine正在访问一个修改过的闭包。我猜这是因为在委托的构造中捕获其引用时,捕获的变量实际上仍然是“null”,因为它是构造函数的参数

为了强制执行正确的用法,我想保证操作不为null,并且是不可变的,到目前为止,我还没有找到任何没有构造函数的方法。我曾考虑过使用构建器模式,但我不知道如何在指定的操作中提供对“self”(这个)的访问,我很担心告诉我的团队忽略修改后的关闭警告

我有一个想法,人们可以创建blueprint/对象,然后将其发送到返回具体对象的构建器/汇编程序类,但这并不能解决我在编译时保证非空的问题


在放弃之前,我希望有一些优雅的解决方案来解决我的问题…

我看不出具有非空
操作的约束与您提供的代码之间的联系。您可以轻松地在构造函数中检查传递的参数,以确保它们是“ok”。如果您像现在这样传递一个委托,那么由开发人员决定不创建这样的操作是的,我想,我编写的早期版本有一个单独的参数(名称),并且action属性有一个公共setter,以便在构造之后可以分配它。(无“modified Close”警告)一个缺陷是,有人可能会忘记设置它,并创建一个命名操作,该操作在使用时不执行任何操作,但不会引发异常(如我在管理NamedAction实例的类中检查null)。我可以做一个“assign once”setter(忽略上面的注释,我不想让开发者做坏事,比如在代理中替换代理)。我可以做一个“分配一次”的二传,这样可以防止它失控,但重新分配并没有明显的效果。另一个缺陷是有人可能忘记设置它,但我可以在处理实例的类中检查null。似乎没有办法使不正确的用法变得难以理解,比如以编译器抱怨的方式对其进行编码。那么,您可以将其作为构造函数的参数。如果为null,则抛出异常。尽管编译时检查不会显示
null
prameter。但这样,在运行时不执行操作就无法创建
NamedAction
。如果不需要公开
操作
,请不要这样做。