c# - 如何传递抽象方法作为引用?

标签 c# methods abstract-class pass-by-reference

我承认,我正在做作业,但我被困在这个问题上(A 部分)。我如何通过通知方法作为铁路信号的引用?我不能只找出在抽象构造函数中调用了哪个类,然后在通知方法中打印类名吗?例如:

铁路用户

private string className;

public RailwayUser()
{ 
    Type type = this.GetType();
    className = type.Name;
}

public void PrintClassName()
{
  Console.Writeline(className);
}

铁路信号类

public void Notify()
{
    foreach(RailwayUser u in _watches)
    {
        u.PrintClassName();
        u.Notice(State)
    }
}

enter image description here

最佳答案

这种代码/设计是有缺陷的,因为它所做的是RailwayUser,将对象引用注册到RailWaySignal中的_watchers列表> 类,当 Notify 被调用时,它依次调用每个用户的公共(public) Notice 方法,这不是 Event Signaling 的方式函数指针 有效。事实上 public _watchers 是危险的,因为它可以被任何用户清除,尽管可以使用属性访问来调节

有问题的代码

public void Notify()
{
    foreach(RailwayUser u in _watches)
    {
        u.PrintClassName();
        u.Notice(State)
    }
}

以下是使用事件和委托(delegate)的实际代码:

正确版本

在线代码片段 - https://www.jdoodle.com/embed/v0/uEc

void Main()
{
    List<RailwayUser> railwayUsers = new List<RailwayUser>();

    railwayUsers.Add(new RailwayUser());
    railwayUsers.Add(new RailwayUser());

    RailwayUser.TestNotification();
}

public enum Colour
{
    Red,
    Green,
    NoSignal
}

public class RailwaySignal
{
    public string Name {get; set;}

    public RailwaySignal(string railwaySignalName)
    {
        Name = railwaySignalName;
    }   

    // Delegate for handling event
    public delegate void RailwaySignalEventHandler(object source, Colour e);

    // Delagate object for handling event
    private RailwaySignalEventHandler _railwaySignalEvent;

    // Event Accessor
    public event RailwaySignalEventHandler RailwaySignalEvent
    {
        add
        {
            lock (this)
            {
                _railwaySignalEvent += value;
            }
        }

        remove
        {
            lock (this)
            {
                _railwaySignalEvent -= value;
            }
        }
    }

    // Invoke Event for subscribed clients
    private void Notify()
    {
        if (_railwaySignalEvent != null)
            _railwaySignalEvent.Invoke(this, Colour.Green);
    }

    // Test the Event Invocation
    public void TestEvent()
    {
        Notify();
    }
}

public class RailwayUser
{
    private static RailwaySignal railwaySignal { get; set;} = new RailwaySignal("Signal1");

    public RailwayUser()
    {
        railwaySignal.RailwaySignalEvent += this.Notice;        
    }

    public static void TestNotification()
    {
        railwaySignal.TestEvent();
    }

    public void Notice(object sender, Colour color)
    {       
        Console.WriteLine($"Notice Called, Colour is :: {color}, Sender is :: {((RailwaySignal)sender).Name}");
    }
}

结果

Notice Called, Colour is :: Green, Sender is :: Signal1
Notice Called, Colour is :: Green, Sender is :: Signal1

重要细节

  • 事件的签名是 (object source, Color e),它有助于将相关信息传递给调用的 RailwayUser,我们现在知道 RailwaySignal 触发了通知 RailwayUser 及其颜色值
  • 事件/委托(delegate)与被调用方法具有相同的签名(这是委托(delegate)/函数指针工作的基础)
  • 为了简化,RailwayUser 是一个非抽象类
  • 事件是使用 RailwaySignal 中的 Notify() 方法执行的,我们在 RailwayUser 中使用 TestNotification() 人为地调用它 仅用于演示目的,但理想情况下应在内部触发并传递当前状态,如颜色
  • FuncAction 这样的预定义委托(delegate)经常用于类似的通知机制,它们在内部使用类似的机制工作,尽管声明了一个显式的 event 在内部是一个 delegate 是一个定义良好的模式,尤其是对于 Ui 控件
  • .Net 框架公开的标准事件具有签名object sender, EventArgs e,其中EventArgs 可以包装从Event executor (RailwaySignal) 到Event receiver (铁路用户)

关于c# - 如何传递抽象方法作为引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50195538/

相关文章:

java - 网络钓鱼扫描程序帮助

java - 如何检查抽象对象的实例是否属于特定的子类

c++ - c++中继承两个类的一个类

c# - 在不计算重复项的情况下计算字符串中子字符串的出现次数

c# - C#中的分号

android - 从 AsyncTask 调用 UI 线程方法

java - 类似汉诺塔的东西

java - 在 Java 的多态性中使用抽象类是一种好的/常见的做法吗?

c# - 二元表达式无法转换为 LINQ 中的谓词表达式

c# - 创建将具有类似于 Dictionary<T,T1> 对象初始值设定项的参数的 c# 方法