C# 私有、静态和只读

Posted

技术标签:

【中文标题】C# 私有、静态和只读【英文标题】:C# private, static, and readonly 【发布时间】:2010-11-01 08:58:01 【问题描述】:

我在查看 log4net 的一些代码时遇到了这个问题。

private static readonly ILog logger = LogManager.GetLogger(typeof(AdminClient));

我想知道为什么你需要私有静态只读。

根据我的理解,私有意味着该变量不能在类外部使用,除非有访问器方法或 get 属性。

静态意味着该变量仅在此文件中起作用。

readonly 意味着您只能从值中读取而不能分配它。

所以,我认为是编写此代码的人。将其声明为私有,因为他们不希望它在类外部使用,并且是静态的,因此不希望它在文件外部使用。但是,如果有一个 get 属性,则静态会阻止这种形式的发生。

我想我可以理解 readonly 并且该值仅用于读取而不是设置。

非常感谢您的建议,

【问题讨论】:

关于这个特定模式的一个有趣的旁白:我曾经将其声明为protected static readonly,这为我赢得了来自 VS 代码分析的“CA2104:不要声明只读可变引用类型”警告。正如here 所提到的,“protected readonly 字段并不是很清楚。正如protected,您可能期望派生类可以初始化该字段。”将声明更改为 private static readonly 修复了此问题。 【参考方案1】: private 任何人都不应在类外(即使在子类中)使用 logger 字段,如果您不设置此项,任何其他类都可以使用您的 logger 来登录您的类名。 static 该属性附加到类,因此它不会重复类的每个实例。如果您不设置此项,则 logger 属性将在系统创建对象的每个实例时占用内存中的额外空间(您误解了这一点)。 只读不应修改记录器字段。

【讨论】:

【参考方案2】:

static not 意味着它不能从其他文件访问——这不是 C。static 关键字意味着记录器对象是类变量而不是实例变量,所以即使当从该类的不同对象访问,它们都将引用同一个记录器对象。

【讨论】:

【参考方案3】:

我认为你误解了静态。静态并不意味着“不能在文件外使用”。静态意味着:每个类都有一个。该声明的作用是创建一个仅分配一次的记录器(静态),仅在类中可用(在派生类中也不可用)(私有),并且在其初始化之后无法写入(只读)。

好问题!

【讨论】:

【参考方案4】:

c# 中的静态表示成员与类相关联,而不是与类的实例相关联。 Readonly 很重要,因为在 c# 中,大多数变量,尤其是这个变量,都是引用变量。 readonly 表示该变量将始终引用相同的记录器。

【讨论】:

【参考方案5】:

readonly 变量与 const 非常相似,因为其值在其整个生命周期内都是恒定的。不同之处在于只读变量在运行时初始化,而 const 在编译时初始化。 静态,用通俗的话来说,意味着变量的实例不依赖于声明它的对象的实例。它的生命周期从函数调用到函数调用持续存在。静态变量的访问速度更快,因为它的存储空间在程序的整个持续时间内都保持分配状态。所以知道了这一点,我们可以回到你的问题。

为什么'logger'是静态成员?这是一个设计决定。我需要知道你是如何使用它来回答这个问题的。为什么它是只读的?因为它似乎被初始化了一次,并且它的实例在整个过程中都被使用。我们可以确保没有其他人篡改 logger 的值,方法是在初始化后立即将其设为“只读”。

【讨论】:

【参考方案6】:

开发人员的意思是,当他们在此类的任何实例中调用 logger.Info(...) 时,他们希望使用通用(静态)实例(因此不需要为每个类创建新的记录器实例),他们想确定它自创建以来没有改变(只读),如果我们在派生类的虚函数中,那么我想确保我不会错误地使用基类(私人的)。

【讨论】:

【参考方案7】:

在私有变量上放置只读标志的原因是声明该变量将始终引用同一个对象。 确实,私有使得它对类外的任何人都不可见,但这样我们可以确保我们没有意外地用新对象覆盖变量,通过编写类似

logger = LogManager.GetLogger(typeof(AdminClient));

我们班的其他地方。使用 readonly 它不会编译(除非它之前没有初始化,并且我们在(静态)构造函数中)

【讨论】:

【参考方案8】:

静态变量属于“类变量”的范畴,类变量是与类而不是类对象相关联的变量,另一方面,实例变量是与类对象相关联的变量,意味着每次类对象初始化此对象将拥有该“实例变量”(非静态)的自己的副本,而静态变量在运行程序中的所有类对象之间共享,例如链表的大小等。 readonly 是用于使变量只读的 c# 关键字,java 不提供这样的功能,您必须编写一个公共方法来访问您不想被调和的变量。

【讨论】:

【参考方案9】:

抱歉,我知道这已经得到了回答,而且它真的很老了,但我想让任何看到这篇文章的人都知道这是你设置“Singleton”模式的方式。任何想了解更多关于问题中的代码示例的人都可能会从了解更多关于单例以及它们的使用方式(调解器、记录器、异步回调等)中受益。

// 关于单身人士的母性资料 http://msdn.microsoft.com/en-us/library/ff650316.aspx http://msdn.microsoft.com/en-us/library/ff650849.aspx

// 关于他们的精彩 SO 讨论 What is so bad about singletons?

【讨论】:

以上是关于C# 私有、静态和只读的主要内容,如果未能解决你的问题,请参考以下文章

静态初始化不适用于 c# 和 xaml

C#各种字段类型对比

C# 中的只读结构体(readonly struct)

C ++中的静态构造函数?我需要初始化私有静态对象

只读和私有方法的问题

C#图解教程 第六章 深入理解类