C# запутался в делегатах, издателях и подписчиках - PullRequest
0 голосов
/ 15 марта 2020

Рассмотрим следующую консольную программу. Он имеет четыре класса: Программа, Атакующий, Защитник и Помощник. Я хочу удалить логи c из класса Defender и использовать делегатов для вызова помощников. Я потратил некоторое время на это и не могу его получить.

Где я могу объявить своего делегата: в Программе или в Защитнике? Где я могу создать экземпляр моего делегата: в Программе или в Защитнике? Где я могу подписать моего делегата: в Программе или в Помощнике?

Я могу опубликовать свои попытки, но это не поможет.

using System;

namespace Delegates19
{
    public class Program
    {
        static void Main(string[] args)
        {
            Attacker a = new Attacker();
            string weapon = "sword";
            a.Attack(weapon);

            Defender d = new Defender();
            d.Help(weapon);

            weapon = "spear";
            a.Attack(weapon);
            d.Help(weapon);
        }
    }
    public class Attacker
    {
        public void Attack(string s)
        {
            Console.WriteLine($"Attacker attacks with {s}");
        }
    }
    public class Defender
    {
        public void Help(string s)
        {
            Console.WriteLine($"Defender is attacked with {s} and calls for help");
            if (s == "sword")
                Helper.Knight();
            if (s == "spear")
                Helper.Bowman();
        }
    }
    public class Helper
    {
        public static void Knight()
        {
            Console.WriteLine($"Knight charges Attacker");
        }
        public static void Bowman()
        {
            Console.WriteLine($"Bowman shoots Attacker");
        }
    }
}

1 Ответ

0 голосов
/ 15 марта 2020

Я действительно не уверен, почему вы хотели бы сделать это, но они оба работают и могут дать вам идеи.

Если я не понимаю вашу потребность в событиях / делегатах, я фактически предпочитаю ваш код этим.

Делегаты:

public class Defender
{
    private static Action SwordAction = Helper.Knight;
    private static Action SpearAction = Helper.Bowman;

    public void Help(string s)
    {
        Console.WriteLine($"Defender is attacked with {s} and calls for help");
        if (s == "sword")
            SwordAction();
        if (s == "spear")
            SpearAction();
    }
}

public static class Helper
{
    public static void Knight()
    {
        Console.WriteLine($"Knight charges Attacker");
    }

    public static void Bowman()
    {
        Console.WriteLine($"Bowman shoots Attacker");
    }
}

События:

static void Main(string[] args)
{
    using (var d = new Defender())
    {
        d.GetHelp += StandardDefenseHelp.Defender_GetHelp;
        d.Help("sword");
        d.Help("spear");
    }
}

public class Defender : IDisposable
{
    public event EventHandler<string> GetHelp;

    private void RaiseGetHelp(string weapon) => GetHelp?.Invoke(this, weapon);

    public void Help(string weapon)
    {
        Console.WriteLine($"Defender is attacked with {weapon} and calls for help");
        RaiseGetHelp(weapon);
    }

    public void Dispose()
    {
        GetHelp = null;
    }
}

public static class StandardDefenseHelp
{
    public static void Defender_GetHelp(object sender, string weapon)
    {
        if (weapon == "sword")
            Knight();
        if (weapon == "spear")
            Bowman();
    }

    private static void Knight()
    {
        Console.WriteLine($"Knight charges Attacker");
    }

    private static void Bowman()
    {
        Console.WriteLine($"Bowman shoots Attacker");
    }
}

Важно: события часто являются причиной утечек памяти, поэтому Defender теперь одноразовый.

Вышеприведенный дизайн может быть полезен, если у вас есть несколько типов «DefenseHelp», и другие ситуации должны происходить, когда защитнику нужна помощь, о которой сам защитник ничего не должен знать.

Но я бы сделал это только если бы это дало какую-то выгоду. Я верю в KISS методологию разработки.

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