了解泛型和Func参数 [英] Understanding generics and Func arguments

查看:59
本文介绍了了解泛型和Func参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果这个问题在某个地方得到了解答,我不会感到惊讶,问题是我不知道如何通过搜索来找到我需要的东西。我已经找到的东西要么过于简单化,要么可以使用,要么解释得很差,以至于我无法将其转化为我自己的项目。我没有接受过事件处理程序,代表等等的正式指令(哎呀,我甚至没有学过实体组件系统或其他设计模式),直到我大学毕业并且已经被聘为程序员,即使这样,它也不是我学习或为我工作学到的东西)。

基本上我想知道的是,Array.Sort<的定义是什么; T>(T []数组,比较<比较>比较)看起来像?



显然有一些泛化正在进行中, myCompareDelegate(...)接受两个任意类型的参数。在我发现的与Func参数有关的几乎所有内容中,Func<>参数需要显式声明的类型,但使用我不熟悉的操作符的一些示例代码除外:

  SomeUtility(arg => new MyType()); 
public void SomeUtility< T>(Func< object,T> converter){
var myType = converter(foo);
}

编译,但我不知道它是什么确实,因此我不知道如何利用它来创建可运行或执行我想要的代码。 我的
$ b

我的这里的目标是能够创建一个事件系统(是的,我知道C#有一个内置的事件系统,但是我再次看到的所有示例代码都被简化为无用点 - 包含侦听器与调度员在同一班级 - 或复杂和无法解释的)。我希望以下内容成立:


  1. 注册事件侦听器的单个函数(适用于任何类型的事件及其子类型) li>
  2. 一个派发事件(仅调用相关监听器)的函数

  3. 能够创建新的事件类型,而无需修改注册函数如果新事件类型扩展了可允许的事件类型(即一个实体只会派发EntityEvents而不是WorldEvent),则处理(处理(在调度器中没有显式类型,除基本事件类外))。

我有一个当前可用的系统,但它要求我的所有处理程序都通过一个单独的onEvent函数,该函数接受一个基本事件对象并计算出它的实际类型,

例如:

  //实体实现IEventDispatcher 
public SomeConstructor(Entity ent){
// public delegate void EventListener(EventBase e ventData);在IEventDispatcher接口中声明
//。
ent.attachEvent(typeof(EntityEventPreRender),new EventListener(onEvent));
ent.attachEvent(typeof(EntityEventPostRender),new EventListener(onEvent));

// EntityEventPreRender extends EntityEventRender extends EntityEvent extends EventBase $ b $ // EntityEventPostRender extends EntityEventRender extends EntityEvent extends EventBase $ b $ public void onEvent(EventBase data){
if(data是EntityEventPreRender)
onPre((EntityEventPreRender)data);
if(data is EntityEventPostRender)
onPost((EntityEventPostRender)data);

public void onPre(EntityEventPreRender evt){}
public void onPost(EntityEventPostRender evt){}

attachEvent()这里是一个接受Type(用作HashMap键)和Delegate并将其存储在列表(HashMap值)中的函数。调度事件只需要传递EventData对象,该对象通过查询其类型(通过evt.GetType())来检索侦听器列表,然后调用它们:listItem(evt)



但我宁愿能够这样做:

  public SomeConstructor(Entity ent){
ent.attachEvent(onPre);
ent.attachEvent(onPost);

public void onPre(EntityEventPreRender evt){}
public void onPost(EntityEventPostRender evt){}

但是我不知道如何做到这一点,因为我不知道如何声明attachEvent()函数以Array.Sort<的方式获取泛型函数参数; T>(T [] array,Comparison comparison)。我得到错误:


方法doSomething< T>(SomeClass.Thing< T>)'的类型参数不能从



解决方案

我想你可能会在寻找如下所示:

  public static class PubSub< TMessage> 
{
private static List
<
动作
<
TMessage
>
> listeners = new List< Action< TMessage>>();

public static void Listen(Action< TMessage> listener)
{
if(listener!= null)listeners.Add(listener);

$ b $ public static void Unlisten(Action< TMessage> listener)
{
if(listeners.Contains(listener))listeners.Remove(listener);


public static void Broadcast(TMessage message)
{
foreach(listener中的var listener)listener(message);
}

}

在上面的代码中,使用PubSub并且为TMessage指定一个类型将在内存中创建一个新的静态类,并为其存储空间分配一个单独的侦听器列表。如果您一直使用基类型作为TMessage类型参数的类型参数,编译器将确保只有TMessage及其子类的替换类型将被允许在该列表中。

然后你会像这样使用它:

  public class SomeMessageType 
{
public int SomeId ;
public string SomeDescription;
}

public class SomePublisher
{

public void DoSomethingCool(string description)
{
var randomizer = new Random ();
...
PubSub< SomeMessageType> .Broadcast(new SomeMessageType(){SomeId = randomizer.Next(),SomeDescription = description});



$ b公共类SomeListener
{

静态SomeListener()
{
PubSub< SomeMessageType> .Listen(SomeMessageEvent);


private static void SomeMessageEvent(SomeMessageType message)
{
//对消息
做些什么}

如果您创建另一个类SomeOtherMessageType,它不会从SomeMessageType继承并对其进行类似的调用,它只会播放给特定类型的听众。



编辑:



这是一个完整的概念证明编译你可以在一个控制台应用程序中运行,以消除您对这项技术的功效可能存在的任何问题。

  using System ; 
使用System.Collections.Generic;

命名空间TestPubSub
{


公共类程序
{

public static void Main(string [ ] args)
{
Program.startListeners();

Program.sendTestMessages();

Program.stopConsoleFromExitingImmediately();


private static void startListeners()
{
SomeListener.Listen();
SomeOtherListener1.Listen();
SomeOtherListener2.Listen();


private static void sendTestMessages()
{
var publisher1 = new SomePublisher();
var publisher2 = new SomeOtherPublisher();

publisher1.DoSomethingCool(Hello world);
publisher2.DoSomethingElse(DateTime.Now);


private static void stopConsoleFromExitingImmediately()
{
Console.ReadKey();
}

}

public static class PubSub< TMessage>
{
private static List
<
动作
<
TMessage
>
> listeners = new List< Action< TMessage>>();

public static void Listen(Action< TMessage> listener)
{
if(listener!= null)listeners.Add(listener);

$ b $ public static void Unlisten(Action< TMessage> listener)
{
if(listeners.Contains(listener))listeners.Remove(listener);


public static void Broadcast(TMessage message)
{
foreach(listener中的var listener)listener(message);
}

}

公共类SomeMessageType
{
public int SomeId;
public string SomeDescription;
}

公共类SomeOtherMessageType
{
public DateTime SomeDate;
public Double SomeAmount;
}

public class SomePublisher
{

public void DoSomethingCool(string description)
{
var randomizer = new Random ();
PubSub< SomeMessageType> .Broadcast(new SomeMessageType(){SomeId = randomizer.Next(),SomeDescription = description});
}

}

public class SomeOtherPublisher
{

public void DoSomethingElse(DateTime when)
{
var randomizer = new Random();
PubSub< SomeOtherMessageType> .Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(),SomeDate = when});



$ b public class SomeListener
{

public static void Listen()
{
PubSub< SomeMessageType> .Listen(SomeMessageEvent);


private static void SomeMessageEvent(SomeMessageType message)
{
Console.WriteLine(Attention!SomeMessageType由SomeListener接收,带\ r \ nid:{ 0} \r\\\
description:{1} \r\\\
,message.SomeId,message.SomeDescription);



$ b public class SomeOtherListener1
{

public static void Listen()
{
PubSub< SomeOtherMessageType> .Listen(SomeMessageEvent);

$ b $ private static void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine(Heads up!SomeOtherMessageType by SomeOtherListener1 with'r\\\
amount: {0} \r\\\
date:{1} \r\\\
,message.SomeAmount,message.SomeDate);



$ b public class SomeOtherListener2
{

public static void Listen()
{
PubSub< SomeOtherMessageType> .Listen(SomeMessageEvent);

$ b $ private static void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine(Yo!SomeOtherMessageType由SomeOtherListener2 withr\\\ nount:{0} \\ r \\\
date:{1} \r\\\
,message.SomeAmount,message.SomeDate);
}

}

}



<再次编辑(使用基于实例的酒吧的概念的替代证明):

以下是使用基于实例的PubSub的概念证明。

 使用System; 
使用System.Collections.Generic;

命名空间TestPubSub
{


公共类程序
{

私有静态PubSub< SomeMessageType> pubSub1 =新PubSub< SomeMessageType>();
private static PubSub< SomeOtherMessageType> pubSub2 =新的PubSub< SomeOtherMessageType>();
private static SomeListener listener1 = new SomeListener();
private static SomeOtherListener1 listener2 = new SomeOtherListener1();
private static SomeOtherListener2 listener3 = new SomeOtherListener2();

public static void Main(string [] args)
{
Program.startListeners();

Program.sendTestMessages();

Program.stopConsoleFromExitingImmediately();
}

private static void startListeners()
{
Program.listener1.Listen(Program.pubSub1);
Program.listener2.Listen(Program.pubSub2);
Program.listener3.Listen(Program.pubSub2);
}

private static void sendTestMessages()
{
var publisher1 = new SomePublisher(Program.pubSub1);
var publisher2 = new SomeOtherPublisher(Program.pubSub2);

publisher1.DoSomethingCool(Hello world);
publisher2.DoSomethingElse(DateTime.Now);


private static void stopConsoleFromExitingImmediately()
{
Console.ReadKey();
}

}

public class PubSub< TMessage>
{
private列表
<
动作
<
TMessage
>
> listeners = new List< Action< TMessage>>();
$ b public void Listen(Action< TMessage> listener)
{
if(listener!= null)this.listeners.Add(listener);
}

public void Unlisten(Action< TMessage> listener)
{
if(listeners.Contains(listener))this.listeners.Remove(listener);
}

public void Broadcast(TMessage message)
{
foreach(this.listeners中的var listener)listener(message);
}

}

公共类SomeMessageType
{
public int SomeId;
public string SomeDescription;
}

公共类SomeOtherMessageType
{
public DateTime SomeDate;
public Double SomeAmount;
}

public class SomePublisher
{

private PubSub< SomeMessageType> PubSub的;

public SomePublisher(PubSub< SomeMessageType> pubSub){this.pubSub = pubSub; }
$ b $ public void DoSomethingCool(string description)
{
var randomizer = new Random();
this.pubSub.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(),SomeDescription = description});
}

}

公共类SomeOtherPublisher
{

私人PubSub< SomeOtherMessageType> PubSub的;

public SomeOtherPublisher(PubSub< SomeOtherMessageType> pubSub){this.pubSub = pubSub; }
$ b $ public void DoSomethingElse(DateTime when)
{
var randomizer = new Random();
this.pubSub.Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(),SomeDate = when});



$ b public class SomeListener
{

public void Listen(PubSub< SomeMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);
}

private void SomeMessageEvent(SomeMessageType message)
{
Console.WriteLine(Attention!SomeMessageType由SomeListener接收,带\ r \ nid:{0 } \r\\\
description:{1} \r\\\
,message.SomeId,message.SomeDescription);



$ b public class SomeOtherListener1
{

public void Listen(PubSub< SomeOtherMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);

$ b $ private void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine(Heads up!SomeOtherMessageType由SomeOtherListener1接收,带\ r\\\
amount:{ 0} \r\\\
date:{1} \r\\\
,message.SomeAmount,message.SomeDate);
}

}

public class SomeOtherListener2
{

public void Listen(PubSub< SomeOtherMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);
}

private void SomeMessageEvent(SomeOtherMessageType消息)
{
Console.WriteLine(Yo!SomeOtherMessageType由SomeOtherListener2 withr\\\
amount:{0} r \\\
date:{1} \r\\\
,message.SomeAmount,message.SomeDate);
}

}

}


I would not be surprised if this has been answered somewhere, the problem is I am not sure how to phrase a search to find what I need. The things I have already found have either been too simplistic to be usable or poorly explained such that I cannot translate it into my own project. I had no formal instruction with event handlers, delegates, and the like (heck, I didn't even learn about Entity-Component Systems--or other design patterns--until long after I graduated college and was already employed as a programmer, and even then it wasn't something I learned at, or for, my job).

Essentially what I want to know is, what does the definition of Array.Sort<T>(T[] array, Comparison<T> comparison) look like?

There's clearly some kind of generalization going on, as myCompareDelegate(...) takes two arguments of any type. In almost everything I've found relating to Func arguments, a Func<> parameter requires explicitly declared types, with the exception of some sample code using an operator I am unfamiliar with:

SomeUtility(arg => new MyType());
public void SomeUtility<T>(Func<object, T> converter) {
    var myType = converter("foo");
}

It compiles but I have no idea what it does and as such, I do not know how to utilize it to create code that will run or do what I want to do.

My goal here is to be able to create an event system (yes, I'm aware that C# has an event system built in, but again, all the sample code I've seen is either simplified to the point of uselessness--listeners contained in the same class as the dispatcher--or complicated and unexplained). I want the following to be true:

  1. a single function to register an event listener (for any Type of event and its subtypes)
  2. a single function to dispatch an event (calling only the relevant listeners)
  3. to be able to create new event types without having to modify the functions for registration and handling (no explicit types in the dispatcher beyond the base event class) provided the new event type extends the allowable event type (i.e. an Entity will only dispatch EntityEvents not WorldEvents).

I have a system that works currently, but it requires that all my handlers pass through a single "onEvent" function which takes a base event object and figures out what it's actual type is, passing that off to the true handler.

Eg:

//Entity implements IEventDispatcher
public SomeConstructor(Entity ent) {
    //public delegate void EventListener(EventBase eventData); is declared
    //in the IEventDispatcher interface.
    ent.attachEvent(typeof(EntityEventPreRender),  new EventListener(onEvent));
    ent.attachEvent(typeof(EntityEventPostRender),  new EventListener(onEvent));
}
//EntityEventPreRender extends EntityEventRender extends EntityEvent extends EventBase
//EntityEventPostRender extends EntityEventRender extends EntityEvent extends EventBase
public void onEvent(EventBase data) {
    if(data is EntityEventPreRender)
        onPre((EntityEventPreRender)data);
    if(data is EntityEventPostRender)
        onPost((EntityEventPostRender)data);
}
public void onPre(EntityEventPreRender evt) {}
public void onPost(EntityEventPostRender evt) {}

attachEvent() here is a function that takes a Type (used as a HashMap key) and a Delegate and stores it in a list (the HashMap value). Dispatching the event just needs to pass the EventData object, which is queried for its type (via evt.GetType()) to retrieve the list of listeners, then invoking them: listItem(evt)

But I'd rather be able to just do this:

public SomeConstructor(Entity ent) {
    ent.attachEvent(onPre);
    ent.attachEvent(onPost);
}
public void onPre(EntityEventPreRender evt) {}
public void onPost(EntityEventPostRender evt) {}

But I cannot, for the life of me, figure out how to do this because I do not know how to declare the attachEvent() function to take a generic function parameter the way Array.Sort<T>(T[] array, Comparison<T> comparison) does. I get the error:

"The type arguments for method doSomething<T>(SomeClass.Thing<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly."

解决方案

I think you might be looking for something like the following:

public  static  class   PubSub<TMessage>
{
    private static  List
                    <
                        Action
                        <
                            TMessage
                        >
                    >                   listeners   = new List<Action<TMessage>>();

    public  static  void                Listen(Action<TMessage> listener)
    {
        if (listener != null)   listeners.Add(listener);
    }

    public  static  void                Unlisten(Action<TMessage> listener)
    {
        if (listeners.Contains(listener))   listeners.Remove(listener);
    }

    public  static  void                Broadcast(TMessage message)
    {
        foreach(var listener in listeners)  listener(message);
    }

}

In the above code, using PubSub and specifying a type for TMessage creates a new static class in memory with its own memory space allocated for storing a separate list of listeners. The compiler will ensure that only the substituted type for TMessage and its subclasses will be allowed in that list, provided you consistently use the base type as the type argument for the TMessage type parameter.

You would then use it like so:

public  class   SomeMessageType
{
    public  int     SomeId;
    public  string  SomeDescription;
}

public  class   SomePublisher
{

    public  void    DoSomethingCool(string description)
    {
        var randomizer  = new Random();
        ...
        PubSub<SomeMessageType>.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
    }

}

public  class   SomeListener
{

    static                  SomeListener()
    {
        PubSub<SomeMessageType>.Listen(SomeMessageEvent);
    }

    private static  void    SomeMessageEvent(SomeMessageType message)
    {
        // do something with the message
    }

}

If you then create another class SomeOtherMessageType which does not inherit from SomeMessageType and make similar calls to it, it will only broadcast to listeners of that specific type.

EDITED:

Here is a full proof of concept that compiles that you can run in a console app to allay any remaining concerns you may have over efficacy of this technique.

using System;
using System.Collections.Generic;

namespace TestPubSub
{


    public  class   Program
    {

        public  static  void    Main(string[] args)
        {
            Program.startListeners();

            Program.sendTestMessages();

            Program.stopConsoleFromExitingImmediately();
        }

        private static  void    startListeners()
        {
            SomeListener.Listen();
            SomeOtherListener1.Listen();
            SomeOtherListener2.Listen();
        }

        private static  void    sendTestMessages()
        {
            var publisher1  = new SomePublisher();
            var publisher2  = new SomeOtherPublisher();

            publisher1.DoSomethingCool("Hello world");
            publisher2.DoSomethingElse(DateTime.Now);
        }

        private static  void    stopConsoleFromExitingImmediately()
        {
            Console.ReadKey();
        }

    }

    public  static  class   PubSub<TMessage>
    {
        private static  List
                        <
                            Action
                            <
                                TMessage
                            >
                        >                   listeners   = new List<Action<TMessage>>();

        public  static  void                Listen(Action<TMessage> listener)
        {
            if (listener != null)   listeners.Add(listener);
        }

        public  static  void                Unlisten(Action<TMessage> listener)
        {
            if (listeners.Contains(listener))   listeners.Remove(listener);
        }

        public  static  void                Broadcast(TMessage message)
        {
            foreach(var listener in listeners)  listener(message);
        }

    }

    public  class   SomeMessageType
    {
        public  int     SomeId;
        public  string  SomeDescription;
    }

    public  class   SomeOtherMessageType
    {
        public  DateTime    SomeDate;
        public  Double      SomeAmount;
    }

    public  class   SomePublisher
    {

        public  void    DoSomethingCool(string description)
        {
            var randomizer  = new Random();
            PubSub<SomeMessageType>.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
        }

    }

    public  class   SomeOtherPublisher
    {

        public  void    DoSomethingElse(DateTime when)
        {
            var randomizer  = new Random();
            PubSub<SomeOtherMessageType>.Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(), SomeDate = when});
        }

    }

    public  class   SomeListener
    {

        public  static  void    Listen()
        {
            PubSub<SomeMessageType>.Listen(SomeMessageEvent);
        }

        private static  void    SomeMessageEvent(SomeMessageType message)
        {
            Console.WriteLine("Attention! SomeMessageType receieved by SomeListener with\r\nid: {0}\r\ndescription: {1}\r\n", message.SomeId, message.SomeDescription);
        }

    }

    public  class   SomeOtherListener1
    {

        public  static  void    Listen()
        {
            PubSub<SomeOtherMessageType>.Listen(SomeMessageEvent);
        }

        private static  void    SomeMessageEvent(SomeOtherMessageType message)
        {
            Console.WriteLine("Heads up! SomeOtherMessageType receieved by SomeOtherListener1 with\r\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
        }

    }

    public  class   SomeOtherListener2
    {

        public  static  void    Listen()
        {
            PubSub<SomeOtherMessageType>.Listen(SomeMessageEvent);
        }

        private static  void    SomeMessageEvent(SomeOtherMessageType message)
        {
            Console.WriteLine("Yo! SomeOtherMessageType receieved by SomeOtherListener2 withr\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
        }

    }

}

EDITED AGAIN (Alternate proof of concept using an instance based pubs):

Here is a proof of concept using an instance based PubSub.

using System;
using System.Collections.Generic;

namespace TestPubSub
{


    public  class   Program
    {

        private static  PubSub<SomeMessageType>         pubSub1     = new PubSub<SomeMessageType>();
        private static  PubSub<SomeOtherMessageType>    pubSub2     = new PubSub<SomeOtherMessageType>();
        private static  SomeListener                    listener1   = new SomeListener();
        private static  SomeOtherListener1              listener2   = new SomeOtherListener1();
        private static  SomeOtherListener2              listener3   = new SomeOtherListener2();

        public  static  void                Main(string[] args)
        {
            Program.startListeners();

            Program.sendTestMessages();

            Program.stopConsoleFromExitingImmediately();
        }

        private static  void    startListeners()
        {
            Program.listener1.Listen(Program.pubSub1);
            Program.listener2.Listen(Program.pubSub2);
            Program.listener3.Listen(Program.pubSub2);
        }

        private static  void    sendTestMessages()
        {
            var publisher1  = new SomePublisher(Program.pubSub1);
            var publisher2  = new SomeOtherPublisher(Program.pubSub2);

            publisher1.DoSomethingCool("Hello world");
            publisher2.DoSomethingElse(DateTime.Now);
        }

        private static  void    stopConsoleFromExitingImmediately()
        {
            Console.ReadKey();
        }

    }

    public  class   PubSub<TMessage>
    {
        private List
                <
                    Action
                    <
                        TMessage
                    >
                >                   listeners   = new List<Action<TMessage>>();

        public  void                Listen(Action<TMessage> listener)
        {
            if (listener != null)   this.listeners.Add(listener);
        }

        public  void                Unlisten(Action<TMessage> listener)
        {
            if (listeners.Contains(listener))   this.listeners.Remove(listener);
        }

        public  void                Broadcast(TMessage message)
        {
            foreach(var listener in this.listeners) listener(message);
        }

    }

    public  class   SomeMessageType
    {
        public  int     SomeId;
        public  string  SomeDescription;
    }

    public  class   SomeOtherMessageType
    {
        public  DateTime    SomeDate;
        public  Double      SomeAmount;
    }

    public  class   SomePublisher
    {

        private PubSub<SomeMessageType> pubSub;

        public                          SomePublisher(PubSub<SomeMessageType> pubSub)   { this.pubSub = pubSub; }

        public  void                    DoSomethingCool(string description)
        {
            var randomizer  = new Random();
            this.pubSub.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
        }

    }

    public  class   SomeOtherPublisher
    {

        private PubSub<SomeOtherMessageType>    pubSub;

        public                                  SomeOtherPublisher(PubSub<SomeOtherMessageType> pubSub) { this.pubSub = pubSub; }

        public  void    DoSomethingElse(DateTime when)
        {
            var randomizer  = new Random();
            this.pubSub.Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(), SomeDate = when});
        }

    }

    public  class   SomeListener
    {

        public  void    Listen(PubSub<SomeMessageType> pubSub)
        {
            pubSub.Listen(this.SomeMessageEvent);
        }

        private void    SomeMessageEvent(SomeMessageType message)
        {
            Console.WriteLine("Attention! SomeMessageType receieved by SomeListener with\r\nid: {0}\r\ndescription: {1}\r\n", message.SomeId, message.SomeDescription);
        }

    }

    public  class   SomeOtherListener1
    {

        public  void    Listen(PubSub<SomeOtherMessageType> pubSub)
        {
            pubSub.Listen(this.SomeMessageEvent);
        }

        private void    SomeMessageEvent(SomeOtherMessageType message)
        {
            Console.WriteLine("Heads up! SomeOtherMessageType receieved by SomeOtherListener1 with\r\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
        }

    }

    public  class   SomeOtherListener2
    {

        public  void    Listen(PubSub<SomeOtherMessageType> pubSub)
        {
            pubSub.Listen(this.SomeMessageEvent);
        }

        private void    SomeMessageEvent(SomeOtherMessageType message)
        {
            Console.WriteLine("Yo! SomeOtherMessageType receieved by SomeOtherListener2 withr\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
        }

    }

}

这篇关于了解泛型和Func参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆