RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 605642
Accepted
αλεχολυτ
αλεχολυτ
Asked:2020-12-20 18:02:02 +0000 UTC2020-12-20 18:02:02 +0000 UTC 2020-12-20 18:02:02 +0000 UTC

本地运行时常量

  • 772

在 C++ 中,要定义本地运行时常量,您可以编写:

const auto c = f();

此外,所有更改尝试都c将导致编译错误。

在 C# 中没有这种可能性。您可以readonly以这种方式使用成员,但不能使用局部常量。

为什么会有这样的限制(C++ 中缺少局部常量的原因是什么)以及在 C# 中强制执行局部运行时恒定性的规范解决方案是什么?真的有必要为此创建一个单独的只读接口吗?

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Grundy
    2020-12-20T18:17:17Z2020-12-20T18:17:17Z

    答案:JaredPar和Jon Skeet

    原因之一是 CLR 缺乏对只读局部变量的支持。只读转换为 CLR/CLIinitonly操作码。该标志只能应用于字段,对局部变量没有意义。事实上,将此代码应用于局部变量很可能会使代码无法验证。

    这并不意味着 C# 无法实现它。但这给同一个语言结构增加了两种含义。局部变量的版本在 CLR 中没有等效映射。


    参考 Jared 的回答,这可能是一个编译时特性——编译器将阻止您在初始声明(必须包含赋值)后写入变量。

    这有什么好处吗?潜力——但老实说并不多。如果您无法判断该方法中的其他地方是否会有赋值,那么您的方法太大了。

    但是,Java 具有此功能(在使用修饰符时final),除了允许在内部匿名类中使用变量之外,我很少看到它在其他情况下的使用——并且在使用它的地方给人的印象是混乱而不是有用信息。


    作为一种解决方法,如果你真的想要,只有你自己承担风险和风险是这样的:

    太好了,多么可怕的例子

    作为运行时常量,您可以在迭代器块中使用变量:

    public void f() 
    {
      foreach (int n in new int[] { getNum() }) // n declared constant
      {
        n = 3; // won't compile: "error CS1656: Cannot assign to 'n' because it is a 'foreach iteration variable'"
      }
    }
    
    • 8
  2. Best Answer
    user177221
    2020-12-20T20:04:33Z2020-12-20T20:04:33Z

    值得注意的是,有一个关于本地只读变量的官方建议。该功能迟到了 C# 7,但它完全有机会进入 C# 8。

    从 CLR 方面来看,实现没有限制——只读局部变量,就像 .NET 4.0 以来的所有 C# 特性一样,是编译时特性——因为 从那时起,运行时版本没有改变。

    事实上,这个提议归结为几点:

    • 将参数标记为的能力readonly
    • 将变量标记为的能力readonly
    • 捷径let-等效readonly var

    本地只读和不可变的foreach iteration variable,首先是防止傻瓜/复制粘贴错误。只有这样 - 一种向编译器指示闭包可能优化的方法。

    在我看来,仅仅为了防止潜在错误而手动将只读分配给局部变量的能力对于实际使用来说是不方便的。回想一下finalJava 就够了。因此,如果没有捷径,该let功能将毫无用处 - 它会被“安全代码”的粉丝使用 - 那些现在基本上不在var泛型的所有引用中使用和显式输入类型的人。

    其余的将采取阻力最小的路径 - 每月修复一个错误比为每个变量分配只读更便宜和容易得多。好吧,再一次,正确应用测试后,可以解决复制粘贴错误的问题。

    实现了更健壮的保护方法,例如,在 F# 中,本地默认值是不可变的,并且=在值声明之外它根本不能作为赋值运算符工作。

    let x = 1
    x = 2 // This expression should have type 'unit', but has type 'bool'
    

    要更改值,开发人员必须在声明变量的行和更改变量的行中进行额外的操作。

    let mutable x = 1
    x <- 2
    

    语言本身促使他声明另一种价值,而不是改变现有的价值。程序员的三大美德之一——懒惰——使他免于犯错误。

    就像那样,将只读添加到变量中,“无论发生什么”——除了特殊的粉丝,没有人会——出于同样的懒惰的原因。

    • 6

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5