C#为什么没有像C语言一样的本地静态变量呢?我很想念它!!
这篇来自2004年的MSDN博客文章:为什么C#不支持静态方法变量?回答了原帖中提出的确切问题:
C#不支持这个特性有两个原因。
首先,通过拥有类级别的静态变量,几乎可以达到相同的效果,而添加方法级别的静态变量会增加复杂性。
其次,方法级别的静态变量在重复调用或从多个线程调用代码时可能会引起问题,并且由于定义在方法中,很难找到定义。
[作者:Eric Gunnerson]
(同一篇博客文章在微软的自己的存档中。Archive.org保留了评论。微软的存档没有。)
状态通常是对象的一部分或类型的一部分,而不是方法的一部分。(当然,被捕获变量是例外。)
如果你想要一个局部静态变量的等效物,请创建一个实例变量或一个静态变量,并考虑该方法本身是否应该成为具有该状态的不同类型的一部分。
所以您想在方法中使用静态局部变量?恭喜!您又迈向了成为一个“真正”的程序员的一步。
不要听那些告诉您静态局部变量不是“干净”的,会影响“可读性”并可能导致微妙且难以找到的“错误”的人。这是无稽之谈!他们这么说只是因为他们是“自命不凡”的程序员!他们中的许多人甚至在业余时间里玩弄某种奇怪的函数式编程语言。你能相信吗?一群时髦的人!
“真正”的程序员拥抱我称之为SDD的范式-“Side effect Driven Design”。以下是其中一些最重要的法律:
不要太过可预测!即使使用完全相同的参数调用,也永远不要从方法中两次返回相同的内容!
放弃纯洁 - 让我们变得“肮脏”起来吧!状态本质上渴望改变,因为它是范畴论中多元态函子的一个无法满足的单子, 也就是说,它希望尽可能多地与协作者互动。永远不要错过这样的机会,让它感到高兴!
在编写副作用驱动代码时使用的工具之一是静态局部变量。然而,正如您所注意到的,C#并不支持它们。为什么?因为在过去的二十年中,微软已经被所谓的清洁代码入侵,他们更喜欢可维护性而非灵活性和控制。你还记得上一次看到我们心爱的蓝屏是什么时候吗?现在猜猜这是谁的错!
不过不用担心!“真正”的开发人员不必受那些糟糕的设计决策之苦。正如之前所提到的,借助于lambda表达式,可以实现一种类似静态的本地变量。var inc = Increment();
var zero = inc();
var one = inc();
或者
var zero = Increment()();
以下是适当的SDD代码:
public Func<int> Increment = new Func<Func<int>>(() =>
{
var num = 0;
return () => num++;
}).Invoke();
你是否认为上面的代码看起来有点像一个 IIFE?是的,你是对的,应该为自己感到羞愧。
现在每次调用 Increment()
它都会返回不同的内容:
var zero = Increment();
var one = Increment();
当然,您也可以使得计数器在实例的生命周期内存活。
这将展示给那些冒牌程序员们!
List<>
等,我将其初始化为null
)无效。有没有办法让它工作?即使我在调用Func
的方法中更改返回的列表,Func
始终返回null
。我以为引用会“粘住”,这样说。 - silkfireAdd()
、Remove()
等方法来改变列表。 - Good Night Nerd PrideC#是一种面向组件的语言,没有类或本地方法范围之外的变量概念。在方法内部声明的变量也不能被声明为静态的,这可能与您在C中习惯的做法不同。但是,您总可以使用类静态变量作为替代。
通常情况下,在C#中解决编程问题时,通常有其他方法而不必使用方法级静态变量。状态通常是应该设计到类和类型中而不是方法中的东西。
lock(myLock){ ... }```
- Benji Altman从逻辑上讲,是的。这与仅在该方法中使用的类级静态成员相同。但是,方法级静态成员将更具封装性。如果存储在成员中的数据仅应由单个方法使用,则应仅由该单个方法访问。
但是,在C#中,您可以通过创建嵌套类几乎完全实现相同的效果。
我认为局部静态变量的想法可以通过创建公共静态字段来很容易地解决。逻辑上几乎没有什么改变,你不觉得吗?
如果您认为这将是一个重大的逻辑改变,我很愿意听听您的见解。
class MyClass
{
public static float MaxDepthInches = 3;
private void PickNose()
{
if (CurrentFingerDepth < MyClass.MaxDepthInches)
{
CurrentFingerDepth++;
}
}
}
你可以使用嵌套类来解决这个问题。由于C#将静态变量的作用域限制在类中,因此你可以使用嵌套类作为作用域。
例如:
public class Foo {
public int Increment() {
return IncrementInternal.Increment();
}
private static class IncrementInternal {
private static int counter = 0;
public static int Increment() {
return counter++;
}
}
}
这里的Foo
支持Increment
方法,但它是通过私有嵌套类IncrementInternal
来支持的,该类包含静态变量作为成员。当然,在Foo
的上下文(其他方法)中,counter
是不可见的。
顺便说一句,如果你想在IncrementInternal.Increment
内部访问Foo
的上下文(其他成员和方法),你可以在从Foo
调用它时将this
作为参数传递给IncrementInternal.Increment
。
为了尽可能地保持范围小,我的建议是为每个这样的方法创建一个嵌套类。因为这可能不是很常见,所以嵌套类的数量足够小,可以维护它。
我认为这比匿名函数或IIFE更清晰。
你可以在这里看到一个实时演示。