在 C# 和函数中理解模板的问题

problem understanding the template in c# and function

文档network and the most importantly documentation: SocketMessageLayer

在 SocketMessageLayer 中有一个我不知道如何调用的函数: public void AddPacketHandler<T>(Func<T, Task> asyncHandler, bool oneTime = false)

我就是这样称呼它的:

    string str = "example";
    public SimpleSocket SS = new SimpleSocket();
    public SocketMessageLayer SML;
    
    
    
    public void Server(){
        //int port, bool singleConnection, int retryCount = 1
        SS.StartServer(21, false, 1);
        SML = new SocketMessageLayer(SS, true);
    }
    public void Client(){
        //string address, int port, bool needAck = true
        SS.StartClient("127.0.0.1", 21, true);
        SML = new SocketMessageLayer(SS, false);
    }
    
    
    
    public async Task SendMessage(string str){
        //public void AddPacketHandler<T>(Func<T, Task> asyncHandler, bool oneTime = false)
        await SML.AddPacketHandler<string>(SomeFunction("ClientSendToServer", await SML.Send(str) ), false  );
        //await SML.Send(str);
        
    }
    
    
    public void SomeFunction(string s, Task Tas){
        str = s;
    }

发送消息

中的问题是Argument 2: cannot convert from 'void' to 'System.Threading.Tasks.Task'

我想做的是将消息发送到服务器或从服务器发送到客户端。我无法理解基础知识。

这里有很多问题。

AddPacketHandler 需要一个 Func<T, Task> 委托作为它的第一个参数,但您正在调用 SomeFunction 而不是将其作为委托传递。

这意味着您正试图传递 SomeFunction 的 return 值,即 void,这是不允许的,因此会出现编译错误。

此外,Func<T, Task> 是一个接受类型为 T 和 return 的单个参数的委托 Task.

您的 SomeFunction 方法接受 TTask 和 return 类型的两个参数 void,因此它不能转换为 Func<T, Task> 不能作为第一个参数传递。

您可以将 SomeFunction 的签名更改为:

public Task SomeFunction(string s)
{
    str = s;
    return Task.CompletedTask;
}

可以这样传:

public async Task SendMessage(string str)
{
    SML.AddPacketHandler<string>(SomeFunction, false);
    await SML.Send(str);        
}

您可能希望将 "ClientSendToServer" 传递给 SendMessage 而不是将其硬编码到该方法中:

await SendMessage("ClientSendToServer");

首先也是最重要的:为什么你 必须 调用 AddPacketHandler?

查看this,PacketHandler 不是强制性的,因此如果您不需要它可以不添加它,尽管对于注册数据包处理程序,您可以通过多种方式进行,这是三个例子:

示例 1

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            // you handler code goes here
            Func<string, Task> func = (str) => Task.Run(() => Console.WriteLine(str));           

            AddPacketHandler(func);
            await _handlers[0]("foo");
        }       

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

示例 2

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            // you can create your handler here
            AddPacketHandler<string>(
                (str) =>
                {
                    return Task.Run(() => Console.WriteLine(str));
                });
            await _handlers[0]("foo");
        }

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

示例 3

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            AddPacketHandler<string>(SomeFunction);         
            await _handlers[0]("foo");
        }

        // you handler code goes here
        private static Task SomeFunction(string s)
        {
            return Task.Run(() => Console.WriteLine(s));
        }

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

句柄本身将被库调用here

此代码基于您告知的文档中的源代码,如果您遇到这样的情况,看看它并了解函数实际做了什么总是很酷。