C# 理解泛型和Func参数
如果这个问题在某个地方得到了回答,我不会感到惊讶,问题是我不知道如何用词组搜索来找到我需要的东西。我已经发现的东西要么过于简单,无法使用,要么解释得很糟糕,以至于我无法将其转化为我自己的项目。我没有关于事件处理程序、委托等方面的正式指导(见鬼,我甚至没有学习实体组件系统——或其他设计模式——直到我大学毕业并被聘为程序员之后很久,即使在那时,我也没有在工作中学过这些东西) 本质上我想知道的是,Array.Sort(T[]Array,Comparison-Comparison)的定义看起来像什么 显然有某种泛化在进行,因为MyCompareLegate(…)接受两个any类型的参数。在我发现的与Func参数相关的几乎所有内容中,Func参数都需要显式声明的类型,但使用我不熟悉的运算符的一些示例代码除外:C# 理解泛型和Func参数,c#,generics,unity3d,C#,Generics,Unity3d,如果这个问题在某个地方得到了回答,我不会感到惊讶,问题是我不知道如何用词组搜索来找到我需要的东西。我已经发现的东西要么过于简单,无法使用,要么解释得很糟糕,以至于我无法将其转化为我自己的项目。我没有关于事件处理程序、委托等方面的正式指导(见鬼,我甚至没有学习实体组件系统——或其他设计模式——直到我大学毕业并被聘为程序员之后很久,即使在那时,我也没有在工作中学过这些东西) 本质上我想知道的是,Array.Sort(T[]Array,Comparison-Comparison)的定义看起来像什么 显
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);
}
}
}