C# params object[] 奇怪的行为

2024-02-02

考虑这段代码

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] strings = new string[] { "Test1", "Test2", "Test3" };

            int[] ints = new int[] { 1, 2, 3, 4 };

            Test(strings);

            Test(ints);
        }

        public static void Test(params object[] objects)
        {
        }
    }
}

还有这个页面https://msdn.microsoft.com/fr-ca/library/w5zay9db.aspx https://msdn.microsoft.com/fr-ca/library/w5zay9db.aspx

我希望 (params object[]objects) 是一个由一个元素组成的数组,其中第一个元素是 string[],但是当我调试时,我看到 (paramsobject[]objects) 是 { "Test1", "Test2 ”,“测试3”}。

但是,使用 int[],我得到一个以 int[] 作为第一个元素的 object[]。

这是未定义的行为吗?这取决于.Net框架版本/Mono版本吗?


不错的发现!

这是未定义的行为吗?

不,这是设计使然。奇怪的设计,但却是有意为之。

这取决于.Net框架版本/Mono版本吗?

不会。所有版本的 C# 都有此行为。

这是 C# 的一些有趣规则发生冲突的结果。

第一个相关规则是:具有 params 数组的方法可以以“正常”或“扩展”形式调用。正常形式就好像没有“params”。扩展形式采用参数并将它们捆绑到自动生成的数组中。如果两种形式都适用,那么普通形式胜过扩展形式.

现在看来,这或许是明智的。如果您手头有一个对象数组,那么您很可能希望传递对象数组,而不是包含对象数组的数组。

第二条相关规则是 C# 允许当元素类型是引用类型时不安全的数组协方差。也就是说,字符串数组可以隐式转换为对象数组。您会注意到这有两个含义。首先,这意味着当你有一个对象数组时,它可能actually是一个字符串数组,因此将海龟放入该对象数组中可能会导致类型错误。这是非常令人惊讶的!您期望每个对象数组都可以接受任何对象,但在 C# 中并非如此。一些物体阵列正在撒谎。

第二个含义是:由于将海龟放入真正的字符串数组中必须抛出,这意味着每次将某些内容放入基本类型数组时,运行时必须验证类型是否检查。所以数组写入在 C# 中是非常昂贵的every写,这样极少数的坏写就可以被捕获。

这是一团糟,这就是为什么不安全的数组协方差在我的不幸的 C# 功能列表中名列前茅。

这两条规则的结合解释了你的观察结果。字符串数组可转换为对象数组,因此该方法适用于正常形式。

对于整数数组,协方差不适用于值类型。因此,整数数组不可转换为对象数组,因此该方法不适用于其正常形式。但整数数组是一个对象,因此它适用于扩展形式。

也可以看看:

为什么 params 会有这样的行为? https://stackoverflow.com/questions/2210519/why-does-params-behave-like-this/2210603#2210603

您的问题可以说是重复的:

有没有办法区分 myFunc(1, 2, 3) 和 myFunc(new int[] { 1, 2, 3 })? https://stackoverflow.com/questions/9685259/is-there-a-way-to-distingish-myfunc1-2-3-from-myfuncnew-int-1-2-3/9711427#9711427

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# params object[] 奇怪的行为 的相关文章

  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 如何在c++中读取pcap文件来获取数据包信息?

    我想用 C 编写一个程序来读取 pcap 文件并获取数据包的信息 例如 len sourc ip flags 等 现在我找到了如下代码 我认为它会帮助我获取信息 但是我有一些疑问 首先我想知道应该将哪个库添加到我的程序中 然后什么是 pca
  • 错误:表达式不产生值

    我尝试将以下 C 代码转换为 VB NET 但在编译代码时出现 表达式不产生值 错误 C Code return Fluently Configure Mappings m gt m FluentMappings AddFromAssemb
  • 为什么极端下派生类(多重虚拟继承)的大小包括超类成员大小的两倍?

    include
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 如何在非控制台应用程序中查看 cout 输出?

    输出到调试窗口似乎相当繁琐 我在哪里可以找到cout如果我正在编写非控制台信息 则输出 Like double i a b cout lt lt b lt lt endl I want to check out whether b is z
  • 不同类型指针之间的减法[重复]

    这个问题在这里已经有答案了 我试图找到两个变量之间的内存距离 具体来说 我需要找到 char 数组和 int 之间的距离 char data 5 int a 0 printf p n p n data 5 a long int distan
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐