C# 理解泛型和Func参数

C# 理解泛型和Func参数,c#,generics,unity3d,C#,Generics,Unity3d,如果这个问题在某个地方得到了回答,我不会感到惊讶,问题是我不知道如何用词组搜索来找到我需要的东西。我已经发现的东西要么过于简单,无法使用,要么解释得很糟糕,以至于我无法将其转化为我自己的项目。我没有关于事件处理程序、委托等方面的正式指导(见鬼,我甚至没有学习实体组件系统——或其他设计模式——直到我大学毕业并被聘为程序员之后很久,即使在那时,我也没有在工作中学过这些东西) 本质上我想知道的是,Array.Sort(T[]Array,Comparison-Comparison)的定义看起来像什么 显

如果这个问题在某个地方得到了回答,我不会感到惊讶,问题是我不知道如何用词组搜索来找到我需要的东西。我已经发现的东西要么过于简单,无法使用,要么解释得很糟糕,以至于我无法将其转化为我自己的项目。我没有关于事件处理程序、委托等方面的正式指导(见鬼,我甚至没有学习实体组件系统——或其他设计模式——直到我大学毕业并被聘为程序员之后很久,即使在那时,我也没有在工作中学过这些东西)

本质上我想知道的是,Array.Sort(T[]Array,Comparison-Comparison)的定义看起来像什么

显然有某种泛化在进行,因为MyCompareLegate(…)接受两个any类型的参数。在我发现的与Func参数相关的几乎所有内容中,Func参数都需要显式声明的类型,但使用我不熟悉的运算符的一些示例代码除外:

SomeUtility(arg => new MyType());
public void SomeUtility<T>(Func<object, T> converter) {
    var myType = converter("foo");
}
attachEvent()这里是一个函数,它接受一个类型(用作HashMap键)和一个委托,并将其存储在列表中(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[]Array,Comparison-Comparison)那样获取泛型函数参数。我得到一个错误:

“无法从用法推断方法doSomething(SomeClass.Thing)”的类型参数。请尝试显式指定类型参数。”


我认为您可能正在寻找以下内容:

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);
    }

}
公共静态类PubSub
{
私有静态列表
<
行动
<
TMessage
>
>侦听器=新列表();
公共静态void侦听器(操作侦听器)
{
if(listener!=null)侦听器。添加(listener);
}
公共静态void Unlisten(操作侦听器)
{
if(listeners.Contains(listener))listeners.Remove(listener);
}
公共静态无效广播(TMessage消息)
{
foreach(侦听器中的var侦听器)侦听器(消息);
}
}
在上面的代码中,使用PubSub并指定TMessage的类型在内存中创建一个新的静态类,它自己的内存空间被分配用于存储一个单独的侦听器列表。编译器将确保该列表中只允许TMessage的替换类型及其子类,前提是您始终使用基类型作为TMessage type参数的类型参数

然后您可以这样使用它:

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
    }

}
公共类SomeMessageType
{
公共int-SomeId;
公共字符串描述;
}
公共类发布者
{
public void DoSomethingCool(字符串描述)
{
var randomizer=new Random();
...
广播(新的SomeMessageType(){SomeId=randomizer.Next(),SomeDescription=description});
}
}
公共类侦听器
{
静态SomeListener()
{
PubSub.Listen(SomeMessageEvent);
}
私有静态void SomeMessageEvent(SomeMessageType消息)
{
//对这个消息做点什么
}
}
如果随后创建另一个类SomeOtherMessageType,该类不继承SomeMessageType并对其进行类似调用,则它将仅广播给该特定类型的侦听器

编辑:

这是一个完整的概念证明,您可以在控制台应用程序中运行,以消除您可能对这项技术的有效性存在的任何顾虑

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);
        }

    }

}
使用系统;
使用System.Collections.Generic;
命名空间TestPubSub
{
公共课程
{
公共静态void Main(字符串[]args)
{
Program.startListeners();
Program.sendTestMessages();
Program.stopconsolefromexitinginstally();
}
私有静态侦听器()
{
有人在听;
另一个监听器1.Listen();
另一个监听器2.Listen();
}
私有静态void sendTestMessages()
{
var publisher1=new SomePublisher();
var publisher2=new SomeOtherPublisher();
发布者1.DoSomethingCool(“你好世界”);
发布者2.DoSomethingElse(DateTime.Now);
}
私有静态void stopconsolefromexitinginstallent()
{
Console.ReadKey();
}
}
公共静态类PubSub
{
私有静态列表
<
行动
<
TMessage
>
>侦听器=新列表();
公共静态void侦听器(操作侦听器)
{
if(listener!=null)侦听器。添加(listener);
}
公共静态void Unlisten(操作侦听器)
{
if(listeners.Contains(listener))listeners.Remove(listener);
}
公共静态无效广播(TMessage消息)
{
foreach(侦听器中的var侦听器)侦听器(消息);
}
}
公共类SomeMessageType
{
公共int-SomeId;
公共字符串描述;
}
公共类SomeOtherMessageType
{
公共日期时间
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);
        }

    }

}
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);
        }

    }

}