不返回值的 C# 字符串函数

本文关键字:字符串 函数 返回值 | 更新日期: 2023-09-27 18:35:06

我对这个函数有问题。

public static string artnetReceiver()
{
    string dataout;
    List<string> dmxString = new List<string>();
    byte[] _dmxData = new byte[511];
    artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>
    {
        if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
        {
            var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
            Console.Clear();
            if (packet.DmxData != _dmxData)
            {
                for (var i = 0; i < packet.DmxData.Length; i++)
                {
                    if (packet.DmxData[i] != 0)
                    {
                    }
                    int temp = i + 1;
                    string chanNum = temp.ToString();
                    string chanValue = packet.DmxData[i].ToString();
                    dmxString.Add(chanNum + "-" + chanValue);
                };
                //dmx stuff
                dataout = string.Join(",", dmxString.ToArray());
                dmxOut = dataout;
                //Console.WriteLine(dataout);//works here
                _dmxData = packet.DmxData;
            }
        }
    };
    return dataout; // doesn't work
}

无论出于何种原因,我构建的字符串都不会到达返回部分,但是当我在函数中进一步使用Console.WriteLine(dataout);时,它会吐出到控制台,但如果我通过其他函数调用它,例如,Console.WriteLine(artnetReceiver());我得到一个空白结果。编辑新代码

public static void artnetReceiver()
        {  
               artnet.NewPacket += OnArtNet_NewPacket;  
        }
       public static string ProcessDataOut(string dataout)
       {
            return dataout;
       }
        /*public static void getDMXPackets()
        {
            artnetReceiver((val) =>
            {
                return val;
            });
        }*/
        public static void OnArtNet_NewPacket(object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e)
        {
            byte[] _dmxData = new byte[511];
            List<string> dmxString = new List<string>();
            string dataout; //included here so the sample will compile
            if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
            {
                var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
                Console.Clear();
                if (packet.DmxData != _dmxData)
                {
                    for (var i = 0; i < packet.DmxData.Length; i++)
                    {
                        if (packet.DmxData[i] != 0)
                        {
                        }
                        int temp = i + 1;
                        string chanNum = temp.ToString();
                        string chanValue = packet.DmxData[i].ToString();
                        dmxString.Add(chanNum + "-" + chanValue);
                    };
                    //dmx stuff
                    dataout = string.Join(",", dmxString.ToArray());
                    dmxOut = dataout;
                    _dmxData = packet.DmxData;
                    ProcessDataOut(dataout);
                }
            }
        }

        byte[] _dmxData = new byte[511];

好的,我现在正在努力解决的问题实际上是稍后在我的代码调用中,例如artnetReceiver(),当它运行时,它会返回字符串值,以便我可以将其导出为数据包字符串,如下所示mstrResponse = "Data: " + artnetReceiver();

不返回值的 C# 字符串函数

这是方法中的事件处理程序,它与您的方法调用异步运行。不能期望在事件句柄中返回变量集。

将值存储在全局范围内的其他位置,或者使用例如回调操作来返回值

Action<T>用法示例

public static void AnotherFunction()
{
    ArtnetReceiver((val) =>
    {
        // do work with the value returned
    });
}
public static void ArtnetReceiver(Action<string> callback)
{
    artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>
    {
        // some stuff going on...
        var dataout = value;
        callback(dataout);
    };
}
冒着对

MichaC的答案基本上有重复答案的风险,以下是我对你为什么观察这种行为的解释,可能有一个更简单的解决方案。

此代码

artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>{
 //code omitted
}

说的是"当artnet在未来的某个时候引发NewPacket事件时,执行{和}之间的代码。

因此,当第一次遇到此代码时,除了运行时记得在发生artnet.NewPacket时返回并执行代码之外,实际上什么都不会发生。

所以考虑到这一点,当你执行artnetReceiver时,事件的顺序或多或少是这样的

  1. 声明dataout没有值。
  2. 您告诉运行时在将来某个时间发生artnet.NewPacket时执行某些代码。顺便说一下,这段代码是匿名委托的形式,它基本上是一个没有返回值的独立 void 函数。
  3. 然后你返回dataout,这当然是空白的。
  4. 稍后,发生artnet.NewPacket事件,并执行委托,但至关重要的是,如果遇到定义委托的最后一个右大括号,运行时将跳出此委托方法,它不会再次继续执行步骤 3! 这是因为从运行时的角度来看,委托不是定义它的函数的一部分,因此它被视为一个完全独立的方法。

也许这会让它更清楚;让我们将事件处理程序委托移动到它自己的一个单独的方法中,在artnetReceiver之外定义:

public static string artnetReceiver()
{
    string dataout;
    List<string> dmxString = new List<string>();
    byte[] _dmxData = new byte[511];
    artnet.NewPacket += OnArtNet_NewPacket;
    return dataout; // doesn't work
}

事件处理程序是

//note the return type - it's void!
public void OnArtNet_NewPacket(object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e)
{
string dataout; //included here so the sample will compile
if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
        {
            var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
            Console.Clear();
            if (packet.DmxData != _dmxData)
            {
                for (var i = 0; i < packet.DmxData.Length; i++)
                {
                    if (packet.DmxData[i] != 0)
                    {
                    }
                    int temp = i + 1;
                    string chanNum = temp.ToString();
                    string chanValue = packet.DmxData[i].ToString();
                    dmxString.Add(chanNum + "-" + chanValue);
                };
                //dmx stuff
                dataout = string.Join(",", dmxString.ToArray());
                dmxOut = dataout;
                //Console.WriteLine(dataout);//works here
                _dmxData = packet.DmxData;
            }
        }
}

因此,您可以清楚地看到,当您将事件处理程序分配给事件时,实际上不会执行任何内容,只有在偶数触发时才会执行代码。

因此,就解决方案而言 - 无论您需要对dataout做什么,都必须从事件处理程序内部启动。最简单的方法是,您可以将流程的下一步封装在与artnetReceiver相同的类中包含的方法中 - 假设您将其称为ProcessDataOut(string dataout)。然后,您只需修改事件处理程序,以便它做的最后一件事调用该方法,传递dataout

_dmxData = packet.DmxData;
ProcessDataOut(dataout);
}

注意:ProcessDataOut 方法不能有返回类型(嗯,它可以 但这毫无意义,因为那里没有什么可以接收 返回值)。因此,无论您需要对数据输出做什么,您 需要在ProcessDataOut方法中执行此操作。这就是如何 异步/事件驱动的代码:)工作

然而,更

优雅(和更灵活)的解决方案是使用MichaC的答案中所示的回调委托(Action或Func),但同样的概念适用;这个委托不能返回任何东西,必须做你尝试实现的任何过程的"下一步"。

这样做的含义是,你很可能需要反转你的应用程序逻辑;也就是说,与其让一些东西在"外面"等待artnetReceiver返回一些东西(它永远不会),你需要在artnetReceiver的ProcessDataOut方法移动这个东西。