【问题标题】:Immutable local 'variables' in C#C# 中的不可变局部“变量”
【发布时间】:2014-06-24 20:59:46
【问题描述】:

我是 C# 新手(主要是 C++ 程序员,其次是 Java,还有一些我不常使用的);我在 Unity 中使用 C#,但我有一个问题似乎与 C# 相关,而不是 Unity。

我已经在某种程度上转向函数式编程,即代替

// C++
int someFunction(int a) {
    int someCalculatedValue = a * a;
    someCalculatedValue /= 2;
    return someCalculatedValue * 3;
}

我会做这样的事情

// Again C++
int someFunction(int a) {
    const int inputSquared = a * a;
    const int inputSquaredHalved = inputSquared / 2;
    return inputSquaredHalved * 3;
}

现在,我想在 C# 中这样做,但我已经尝试过了

// C#
const float maxGrowth = GrowthRate * Time.deltaTime;

但 Mono 抱怨说 maxGrowth 没有被分配一个“常量值”——所以我假设 C# 的 const 关键字实际上等同于 C++11 中的“constexpr”?

如果是这样,有没有办法在 C# 中做我想做的事?最好不要调用某些容器类(除非编译器擅长提高效率?)。

我认为从我读过的内容来看,C# 在语言上比 C++ 更接近于 Java;不可变类而不是 const 成员函数?

【问题讨论】:

  • 您的标题谈到了不可变的 local 变量,但您的问题只提到了“类似这样的东西”(那是 C++ 吗?)和“我想要什么”(什么?)。你能解释一下你想要这个代码做什么,或者具体来说const做什么?你读过How to declare a local constant in C#?What does immutable and readonly mean in C#?吗?
  • '一个似乎与 C# 相关而不是 C# 的问题。'道格你能解决这个问题吗?
  • 几乎所有 c# 的原始类型都是可变的,因为它们的行为就像一个值的可变容器。我真的建议你看看更好、更实用的 C# 兄弟 - F#
  • 如果你愿意,你可以使用匿名类型。 var inputSquared = new { Value = a * a }; var inputSquaredHalved = new { Value = inputSquared.Value / 2 }; return inputSquaredHalved.Value * 3; Kinda 在语法方面很糟糕,并将其推送到具有只读字段的对象。不知道这在优化或性能方面如何 JIT。
  • @mikez:哈,是的,很公平。最后,C# 中确实没有类似物(但它们倾向于增加更多的不变性,所以也许你会为 C#7 祈祷?)。我应该澄清一下:我的 cmets 只是为了概念讨论(或笑);我真的不赞成使用它们中的任何一个。在 C# 的思维方式中,最好只使用微小的纯方法。

标签: c# immutability


【解决方案1】:

您可以将局部变量声明为迭代变量。迭代变量是只读的。 是的,很丑。

foreach (float maxGrowth in new[] { GrowthRate * Time.deltaTime })
{
  maxGrowth = 0; // won't compile: "error CS1656: Cannot assign to 'maxGrowth' because it is a 'foreach iteration variable'"
}

【讨论】:

  • 哇,这太丑了。但是很有趣,值得一试
【解决方案2】:

readonly

当字段声明包含只读修饰符时,对由声明引入的字段的赋值只能作为声明的一部分或在同一类的构造函数中发生。

没有等效的局部变量。您必须将其设为字段。

【讨论】:

  • 这不适用于 local 变量,这是 OP 所要求的。
  • 各位,请阅读我的完整答案。
  • 最后一句话从一开始就在那里吗?我本可以发誓我之前确实读过它,但如果没有,我很抱歉。我不认为“使它成为一个字段”的指导是适用的 - 查看示例,其中值取决于参数。除非您建议将方法调用转换为自己的类,否则这不是替代方案。
  • OP 也没有将其称为常量 :) 但是明确哪些局部变量可能会改变,哪些可能不是某些函数式语言(例如 F#)的明确风格。我认为“不,你不能在 C# 中做到这一点”可能比个人提及 readonly 更合适。
  • 我以为我说得很清楚,但无论如何。在 Stack Overflow 上的回答中简单地说“不,你不能”有其自身的问题。
【解决方案3】:

我认为这种情况下更好的方法是使用语句

示例:

using (var font = new Font("Arial", 10.0f)) 
{
    byte charset = font.GdiCharSet;
}

字体变量是不可变的

参考:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement

【讨论】:

  • float 没有实现 IDisposable,我看不出这是如何回答问题的。
  • 我明白这个问题不仅仅是关于原始类型的问题,但我尊重你的评论,我也考虑过这个问题
  • 由于这个问题显然是为学习C#的人准备的,所以这个回答很有价值。因此投了赞成票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-30
  • 2015-10-03
相关资源
最近更新 更多