将委托声明传递给 class,然后更改其要调用的值

Passing delegate declaration to a class and then later changing its value to be invoked

我想将委托声明传递给 class,稍后将由另一个 class 分配,然后由第一个 class 调用。我在下面代码中指示的行中收到 NullReferenceException。如何更改代码以获得所需的行为?

class FirstClass
    {
        public Func<bool> funct;

        public FirstClass(Func<bool> funct)
        {
            this.funct = funct;
        }

        public void callFunc()
        {
            funct.Invoke();  // NullReferenceException
        }
    }

    class Program
    {
        public static Func<bool> testFunction;

        static void Main(string[] args)
        {
            FirstClass firstClassInstance = new FirstClass(testFunction);

            var secondClassInstance = new SecondClass();

            firstClassInstance.callFunc();
        }
    }

    class SecondClass
    {
        public SecondClass()
        {
            Program.testFunction = isManipUnderCursor;
        }

        private bool isManipUnderCursor()
        {
            return true;
        }
    }

当您将 testFunction 传递给 FirstClass 时,它为空,因为 testFunction 尚未初始化或分配。在这种情况下,传递的引用不指向该值的未来位置,但它指向 null 并且永远如此。

如果您想调用 Program.testFunction 的当前值,请调用 Program.testFunction

    public void callFunc()
    {
        Program.testFunction?.Invoke();  
    }

或者您提供一个代码来更改 FirstClass.funct 的值,并调用它:

class FirstClass{
  ...
  public void ChangeFuncTo(Func<bool> newFunc){
    funct = newFunc;
  }
  ...
}


        FirstClass firstClassInstance = new FirstClass(testFunction);

        var secondClassInstance = new SecondClass();

        firstClassInstance.ChangeFuncTo(Program.funct);

你安排的这整件事在结构、封装和连贯的 class 职责方面相当糟糕。如果你能 post 一个实际的用例来说明真正的目标是什么,那就太好了,所以我们可以建议,但一般来说你应该像对待数据一样对待函数;如果您只知道在完成构造和使用其他对象后首先要 class 的函数执行什么操作,请不要依赖静态来传递新函数;在第一个 class 上提供并调用一个方法来设置新行为。努力找到在代码中避免 static 的方法。

        //we need to make FirstClass for some reason, before we can generate the fun it will use
        FirstClass firstClassInstance = new FirstClass();

        //second class is a func generator
        var secondClassInstance = new SecondClass();
        
        //now we can generate the func and set it
      

firstClassInstance.ChangeFuncTo(secondClassInstance.GetNewFunc());

        //second class is a func generator, it can generate before firstclass is made
        var secondClassInstance = new SecondClass();
        
        //now we can generate the func and set it
        FirstClass firstClassInstance = new FirstClass(secondClassInstance.GetFunc());

在 C# 中,您不能“通过更改其他一些简单变量指向的内容来更改一些简单变量指向的内容”。用旧数据的简单术语来解释它:

string first = "this is the first string";
string second = first
first = "something else";

second 仍将引用“这是第一个字符串”的值。当您建立额外的引用时,它们不会链接。当你写 string first = "this is the first string"; 时,它给我们这样的记忆:

first --> "this is the first string"

然后你写 string second = first 这给了我们这样的记忆:

first --> "this is the first string" <-- second

最后你写 first = "something else" 这给了我们这样的记忆:

          "this is the first string" <-- second

first --> "something else"

更改 first 从未影响 second。当写 string second = first 时,你不会在内存中得到链式引用,像这样:

second --> first --> "this is the first string" 

这样改变 first 会导致 second 看到它:

second --> first --.    //"this is the first string" garbage collected
                    `-> "something else"