Почему делегаты могут использоваться взаимозаменяемо для методов класса и статических функций? - PullRequest
3 голосов
/ 10 августа 2010

Я использую делегатов в течение многих лет, и на самом деле не особо задумывался о них Но недавно я понял, что делегаты включили в подпись ссылку 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;
    }
}

Почему я могу добавлять как статических, так и экземпляров подписчиков?

    delegate int addDelegate(int x, int y);

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

        private void useDelegates()
        {
            addDelegate algorithm;
            algorithm = SomeStaticClass.StaticAdd;
            algorithm += new SomeClass(3).ClassAdd;

            int answer = algorithm(5, 10);
        }
    }

Что на самом деле происходит ? ;)

Ответы [ 3 ]

4 голосов
/ 10 августа 2010

Если вы создаете делегат, ссылающийся на метод экземпляра, он захватывает this (или соответствующую ссылку) в поле, поддерживающем свойство Target делегата.Если вы создаете делегат со ссылкой на статический метод, Target будет иметь значение null.Логически нет необходимости иметь экземпляр, если вы используете статический метод.

В качестве одной из сложностей вы можете захватывать extension методы, как если бы они были методами экземпляра в расширенном типе:

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"
    }
}

Что касается , почему вы можете сделать все это: потому что это полезно, и нет никаких причин не , чтобы позволить вам сделать это:)

1 голос
/ 10 августа 2010

Прелесть делегатов в том, что они просто работают как для статических, так и для экземпляровых методов.Если вы назначаете статический метод делегату, статический метод просто используется как есть, так как для его работы не требуется нестатического контекста.Для методов экземпляра ссылка на экземпляр сохраняется вдоль указателя метода, так что необходимый контекст (ссылка this) доступен при вызове метода.Это означает, что при назначении метода экземпляра делегату вы также должны предоставить экземпляр - либо указав его явно, либо назначив делегату из контекста экземпляра.«просто работает», и вам не нужно ни о чем думать.Однако есть одно предупреждение: если вы назначаете метод экземпляра делегату, вы создаете другую ссылку на экземпляр, и пока метод остается назначенным делегату (или подписан на событие), также будет ссылкаэкземпляр, поэтому GC никогда не соберет его.Вот почему вы всегда должны отписываться от всех событий при уборке после себя.

1 голос
/ 10 августа 2010

В C # нет статических функций, они на самом деле являются статическими методами (поэтому есть статические методы и методы экземпляров). Каждый делегат в основном является указателем на метод и this указателем, по которому будет выполняться метод, это свойство Target делегата. В случае статического метода он будет нулевым. Поскольку делегат переносит ссылку на объекты, это может вызвать утечку памяти, если вы забудете отписаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...