【问题标题】:Is there a way to implement "void func(out params object[] parameters)" in C#有没有办法在 C# 中实现“void func(out params object[] parameters)”
【发布时间】:2011-03-19 06:20:14
【问题描述】:

我想做的是能够将任意数量的变量传递给函数,在函数内部操作这些变量,并在函数范围之外访问这些操作。

例子

void FunctionA()
{
    int x = 1;
    string s = "blah";
    int y = 4;
    FunctionB(out x, out s, out y);
    Console.WriteLine("{0}, {1}, {2}", x, s, y);
}
void FunctionB(out params object[] parameters)
{
    for(int ii = 0; ii < parameters.Length; ii++)
    {
        if(parameters[ii] is int) parameters[ii] = (int)parameters[ii] + 1;
    }
}

调用 FunctionA() 后,控制台上应该有“2, blah, 5”。有没有办法做到这一点,而不是返回一个 object[] 并解析出我想要的变量?

为了澄清,这就是我想要做的。将一个 byte[] 与一系列变量一起传递给一个函数。尝试从 byte[] 中读取信息并将其分配给传入的变量。因此,如果我将一个 int、一个字符串和另一个 int 写入 byte[] 并传入如下内容:

int x, y;
string s;
byte[] info = ...;
FunctionB(info, x, s, y);
Console.WriteLine("{0}, {1}, {2}", x, s, y);

它会从 byte[] 输出信息。

【问题讨论】:

  • 不编译。 “参数不能具有所有指定的修饰符;参数上的修饰符太多”“参数”错误

标签: c# params out


【解决方案1】:

不,你不能。

这里你有一个单独的输出参数,而你需要几个单独的输出参数。 C# 不支持通过 params... 和 params 是获取不同数量参数的唯一方法,除非您想将其重载到您想要支持的最大参数数量。

params 将始终将参数的 复制到新数组中。那时它们与原始变量无关。

【讨论】:

  • 难道 FunctionB(out int a, out string b, out int c) 算作几个单独的 out 参数吗?因为这确实有效......我只是不知道如何使输出参数的数量动态化。
  • @mphair:是的,这是几个输出参数——但不是通过参数。为不清楚而道歉。将编辑。
  • 这样做的原因是,如果可以有一个变量引用数组,那么该数组的寿命可能比堆栈上的变量引用长。这是 C 程序中非常常见的错误;它在 CLR 程序中永远不会发生,因为根本不可能保持这样的引用。
  • @Eric,如果您在堆栈上有一个 C char[] 并将其作为 char* 传递给某个想要保留它以供参考的函数,那总是特别有趣。我很高兴“使用 malloc 还是不使用 malloc”不再是一个问题。
【解决方案2】:

你确定你需要出局吗?你能给我们真实的代码吗?从我可以告诉你发布的内容来看,这很有效......

void Main()
{
    object [] f = new object []{ 1, "blah", 4 };
    Test( f );
    Console.WriteLine("{0}, {1}, {2}", f[0], f[1], f[2]);
    // output
    // 2, blah, 5 

}

void Test ( object[] parameters )
{
    for(int ii = 0; ii < parameters.Length; ii++)
    {
        if(parameters[ii] is int) 
            parameters[ii] = (int)parameters[ii] + 1;
    }
}

【讨论】:

  • 问题在于,在我将两个整数和字符串包含在 object[] 中之后,我需要将它们解析出来。此解决方案类似于使 Test(object[]) 返回 object[]。使用 out 关键字的想法是,我不必进行任何解析......只需将一些变量放入其中,然后立即开始使用它们。
  • 通过解析,我的意思是必须调用 f[0] vs x。此外,使用您的代码,我必须将我想要的所有内容打包到 object[] 中,然后再将其发送到函数。这就是我试图解决的问题。
【解决方案3】:

您知道,您的“澄清”与您最初的问题完全不同。听起来您正在尝试编写反序列化代码。首先,阅读MSDN Serialization 文档以了解有关 .NET 可以提供的功能的更多信息。如果创建自反序列化对象对于您的特定情况来说是多余的,您应该考虑使用BinaryReader 来读取数据:

byte[] info...
int x;
string s;
int y;

using (BinaryReader reader = new BinaryReader(new MemoryStream(info)))
{
    x = reader.ReadInt32();
    s = reader.ReadString();
    y = reader.ReadInt32();
}

请注意,如果您的数据编码与 BinaryReader 的预期不匹配,您可能必须在 BinaryReader.ReadeByte() 之上构建自己的函数。另请注意,从缓冲区填充“大量变量”的函数有一些代码气味......这些变量肯定以某种方式相关,并且您有机会定义一个代表的类(使用反序列化器!)不管那个概念是什么。

【讨论】:

  • 是的,我正在尝试将 MemoryStream/BinaryReader/BinaryWriter 调用合并到一个通用静态类中。调用 MemoryStream 后 ostream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ostream); writer.Write(...); writer.Write(...);... 很多次,我试图进行通用的读/写调用,这样我就可以传入任意数量的参数,并得到一个 byte[] 输出...或传入一个字节 [] 和我想从字节 [] 中读取的尽可能多的变量。我有序列化的能力......我只是想精简它。
  • 你控制你正在阅读的二进制格式吗?如果是这样,利用内置的 .NET 序列化代码将是迄今为止最简单的。您所要做的就是标记要序列化的字段,然后让 .NET 处理其余部分。
猜你喜欢
  • 2011-05-22
  • 2021-08-25
  • 2012-03-03
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-07
相关资源
最近更新 更多