草庐IT

c# - 为什么不允许重新分配的集合初始值设定项?

coder 2024-05-23 原文

我一直认为这两种方式都很好。然后做了这个测试并意识到它不允许重新分配:

int[] a = {0, 2, 4, 6, 8};

工作正常,但不是:
int [ ] a;
a = { 0, 2, 4, 6, 8 };

这有什么技术原因吗?我想我会在这里询问它,因为这种行为是我直觉上所期望的。

最佳答案

首先,让我们正确理解这些术语。那不是集合初始值设定项。那是一个数组初始值设定项。集合初始值设定项始终遵循集合类型的构造函数。数组初始值设定项仅在局部或字段声明初始值设定项或数组创建表达式中才是合法的。

您完全正确地注意到这是一个奇怪的规则。让我准确地描述它的怪异之处:

假设您有一个方法 M 接受一个整数数组。所有这些都是合法的:

int[] x = new[] { 10, 20, 30 };
int[] y = new int[] { 10, 20, 30 };
int[] z = new int[3] { 10, 20, 30 };
M(new[] { 10, 20, 30 });
M(new int[] { 10, 20, 30 });
M(new int[3] { 10, 20, 30 });


int[] q = {10, 20, 30}; // legal!
M( { 10, 20, 30 } ); // illegal!

似乎“单独”数组初始值设定项在“装饰”数组初始值设定项所在的任何地方都应该合法,或者在任何地方都不合法。奇怪的是,这个伪表达式仅在初始化程序中有效,而在表达式合法的其他任何地方都无效。

在对这个选择进行批评和辩护之前,我想首先声明,这种差异是一个历史偶然。没有令人信服的充分理由。如果我们可以在不破坏代码的情况下摆脱它,我们会的。但我们不能。如果我们今天再次从头开始设计 C#,我认为没有“new”的“单独”数组初始值设定项很可能不是有效的语法。

所以,让我首先给出一些为什么不应该允许数组初始值设定项作为表达式而应该允许在局部变量初始值设定项中的原因。然后我会给出一些相反的理由。

不应允许数组初始值设定项作为表达式的原因:

数组初始值设定项违反了 { 的 nice 属性总是意味着引入新的代码块。 IDE 中的错误恢复解析器在您键入时进行解析,它喜欢使用大括号作为判断语句何时不完整的便捷方式;如果你看到:
if (x == M(
{ 
   Q(

然后代码编辑器很容易猜到您遗漏了 ))之前{ .编辑器将假定 Q(是一个语句的开始,它没有结束。

但是如果数组初始值设定项是合法的表达式,那么可能缺少的是 )})){}关注 Q .

其次,作为表达式的数组初始值设定项违反了所有堆分配在某处都有"new"的好原则。

应在字段和本地初始值设定项中允许数组初始值设定项的原因:

请记住,数组初始值设定项是在 v1.0 中添加到语言中的,之前是隐式类型的局部变量、匿名类型或对数组的类型推断。回到过去,我们没有令人愉快的“new[] { 10, 20, 30}”语法,因此如果没有数组初始值设定项,您必须说:
int[] x = new int[] { 10, 20, 30 };

这似乎很多余!我可以理解为什么他们想要从那里获得“new int[]”。

当你说
int[] x = { 10, 20, 30 };

它在语法上没有歧义;解析器知道这是一个数组初始值设定项而不是代码块的开始(与我上面提到的情况不同)。它也不是类型不明确的;很明显,初始值设定项是来自上下文的整数数组。

因此,该参数证明了为什么在 C# 1.0 数组初始值设定项中允许在本地和字段初始值设定项中但不允许在表达式上下文中。

但这不是我们今天所处的世界。如果我们今天从头开始设计,我们可能不会有没有“new”的数组初始值设定项。当然,现在我们意识到更好的解决方案是:
var x = new[] { 10, 20, 30 };

并且该表达式在任何上下文中都有效。您可以在 = 的“声明”端或“初始化器”端显式键入它如果您认为合适,或者您可以让编译器推断任一方或两者的类型。

所以,总而言之,是的,您是对的,数组初始值设定项只能在本地和字段声明中,而不能在表达式上下文中,这是不一致的。十年前这样做是有充分理由的,但在具有类型推断的现代世界中,它不再有充分理由。在这一点上,这只是一个历史事故。

关于c# - 为什么不允许重新分配的集合初始值设定项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8621250/

有关c# - 为什么不允许重新分配的集合初始值设定项?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  3. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  6. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  7. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  8. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  9. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

随机推荐