如何将抽象方法作为参考传递?

时间:2018-05-06 01:41:27

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

我会承认,我正在做作业而且我坚持这一个问题(A部分)。我如何通过通知方法作为铁路信号的参考?我能不能找出在抽象构造函数中调用哪个类,然后在notify方法中打印类名?例如:

RailwayUser

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

2 个答案:

答案 0 :(得分:2)

这种代码/设计存在缺陷,因为它的作用是RailwayUser,将对象引用注册到_watchers类中的RailWaySignal列表,后者又调用公共调用Notice时每个用户的Notify方法,而不是Event SignalingFunction Pointer的工作方式。实际上公共_watchers是危险的,因为它可以被任何用户清除,尽管可以使用属性访问来审核

问题代码

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

以下是使用事件和代表的实际代码:

正确版本

在线代码段 - 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, Colour e),它有助于将相关信息传递给被调用的RailwayUser,我们现在知道RailwaySignal触发了对RailwayUser的通知及其颜色值
  • 事件/委托与被调用方法具有相同的签名(这是委托/函数指针工作的基础)
  • 为简化起见,RailwayUser是一个非抽象类
  • 使用Notify()内的RailwaySignal方法执行事件,我们在TestNotification()内使用RailwayUser人工调用它仅用于演示目的,但理想情况下它应在内部触发并且应该传递像Color
  • 这样的当前状态
  • FuncAction之类的预定义代理经常用于类似的通知机制,它们在内部使用类似的机制,虽然声明一个明确的event,它在内部是{{ 1}}是一个定义良好的模式,特别是对于Ui控件
  • .Net框架公开的标准事件具有签名delegate,其中object sender, EventArgs e可以将事件执行者(RailwaySignal)中的所有信息包装到事件接收者(RailwayUser)

答案 1 :(得分:1)

它看起来像一个Observer模式。您可以将从RailwayUser对象实例继承的SubClass传递给RailwaySignal

您的RailwayUser课程需要创建public abstract void Notice(Colour state)方法。

public abstract class RailwayUser
{
    private string className;

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

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

    public abstract void Notice(Colour state);
}

Driver类可以继承RailwayUser类,然后覆盖通知方法。

public class Driver : RailwayUser
{
    public override void Notice(Colour state)
    {
        Console.WriteLine($"Driver see the {state.ToString()}");
    }
}

  1. List<RailwayUser> _watches包含可观察对象
  2. SubScript(RailwayUser user)列表中使用_watches订阅用户。
  3. RailwayUser Notify()调用所有可观察的Notify方法。
  4. 看起来像这样。

    public class RailwaySignal
    {
    
        private List<RailwayUser> _watches;
    
        public Colour Stata { get; set; }
    
        public RailwaySignal()
        {
            _watches = new List<RailwayUser>();
        }
    
        public void SubScript(RailwayUser user)
        {
            _watches.Add(user);
        }
    
        public void Notify()
        {
            foreach (RailwayUser u in _watches)
            {
                u.PrintClassName();
                u.Notice(Stata);
            }
        }
    }
    

    样品:https://dotnetfiddle.net/GcdGMy

    您还可以使用event将方法传递到RailwaySignal,然后调用Notify方法。

    public enum Colour
    {
        Green,
        Red,
        Disable
    }
    public abstract class RailwayUser
    {
        private string className;
    
        public RailwayUser()
        {
            Type type = this.GetType();
            className = type.Name;
        }
    
        public void PrintClassName()
        {
            Console.WriteLine(className);
        }
    
        public abstract void Notice(Colour state);
    }
    
    public class Driver : RailwayUser
    {
        public override void Notice(Colour state)
        {
            Console.WriteLine("Driver see the "+ state.ToString());
        }
    }
    
    public class Controller : RailwayUser
    {
        public override void Notice(Colour state)
        {
            Console.WriteLine("Controller see the " + state.ToString());
        }
    }
    
    
    public class RailwaySignal
    {
        public delegate void NoticeEvent(Colour state);
    
        public event NoticeEvent Notifys;
        public Colour Stata { get; set; }
    
        public void Notify()
        {
            if (Notifys != null)
            {
                Notifys(Stata);
            }
        }
    }
    

    像这样使用。

    RailwaySignal railway = new RailwaySignal() { Stata = Colour.Green};
    
    railway.Notifys += new Driver().Notice;
    railway.Notifys += new Controller().Notice;
    
    railway.Notify();
    

    示例:https://dotnetfiddle.net/GcdGMy