繁体   English   中英

为什么委托可以互换用于类方法和静态函数?

[英]Why can delegates can be used interchangeably for Class methods and Static functions?

我使用委托很多年了,并没有真正考虑过它们。 但是我最近因为假设委托在引用类方法时存储了this引用而大吃一惊。 下面的例子说明了我理解上的差距。

public class SomeClass
{
    public SomeClass(int someProperty)
    {
        SomeProperty = someProperty;
    }

    public int SomeProperty
    { 
        get; 
        set; 
    }

    // Throw in a Member field into the mix
    public int ClassAdd(int x, int y)
    {
        return x + y + SomeProperty;
    }
}

public static class SomeStaticClass
{
    public static int StaticAdd(int x, int y)
    {
        return x + y;
    }
}

为什么我可以同时添加静态和实例订阅者?

class TestClass
{
    delegate int myAddDelegate(int x, int y);

    private void UseDelegates()
    {
        myAddDelegate algorithm;
        algorithm = new SomeClass(3).ClassAdd;
        // Surprised that I could add static methods to my delegate?
        algorithm += SomeStaticClass.StaticAdd;

        // I'm fine with just one of the results being returned.
        int answer = algorithm(5, 10);
    }
}

到底发生了什么? ;)

如果您创建引用实例方法的委托,它将在支持委托的Target属性的字段中捕获this (或相关引用)。 如果您创建引用静态方法的委托,则Target将为 null。 从逻辑上讲,如果您使用的是静态方法,则不需要实例。

作为一个额外的复杂性,您可以捕获扩展方法,就好像它们是扩展类型的实例方法一样:

static class Extensions
{
    public static void Foo(this string x)
    {
        Console.WriteLine("Calling Foo on " + x);
    }
}

class Test
{
    static void Main()
    {
        Action action = "text".Foo;
        Console.WriteLine(action.Target); // Prints "text"
    }
}

至于为什么你可以做到这一切:因为它很有用,没有理由不让你这样做:)

C#中没有静态函数,它们实际上是静态方法(所以有静态方法和实例方法)。 每个委托基本上都是指向方法this指针和方法将在其上执行的指针,它是委托的Target属性。 在静态方法的情况下,它将为空。 由于委托携带对对象的引用,如果您忘记取消订阅,它可能会导致内存泄漏。

委托的美妙之处在于它们对静态和实例方法都有效。 如果将静态方法分配给委托,静态方法将按原样使用,因为它不需要任何非静态上下文即可工作。 对于实例方法,对实例的引用与方法指针一起存储,以便在调用方法时可以使用必要的上下文( this引用)。 这意味着当您将实例方法分配给委托时,您还必须提供一个实例 - 通过显式指定它,或者通过从实例上下文内部分配给委托。

大多数时候,这“行之有效”,您无需考虑任何事情。 但有一个警告:如果将实例方法分配给委托,则会创建对该实例的另一个引用,并且只要该方法仍然分配给委托(或订阅事件),也会有一个对实例的引用实例,因此 GC 永远不会收集它。 这就是为什么您在清理自己时应该始终取消订阅所有事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM