什么是受保护字段的正确的符合 CLS 的命名约定?

发布于 2024-12-06 11:04:13 字数 742 浏览 0 评论 0原文

我正在开发一个符合 CLS 的类型库,里面有一个类,其中包含私有、受保护和公共字段和属性。我使用下划线符号 (_) 作为私有或受保护字段的前缀,并使用小首字母来区分它们与具有相同名称的属性。看起来是这样的:

class SomeClass
{
private int _age; //Here is OK

public int Age { get { return this._get; } }
}

但是当我尝试使用受保护的字段时,我遇到了下一个问题:

class SomeClass
{
protected int _age; //Here is NOT CLS-compliant (because of _ can't be the first symbol of identifier)

public int Age { get { return this._get; } }
}

然后我尝试这样做:

class SomeClass
{
protected int age; //Here is NOT CLS-compliant (because of age and Age differ only in one symbol)

public int Age { get { return this._get; } }
}

请告诉我,对于这种情况,开发人员之间正确的 CLS 兼容符号或约定是什么?我必须使用像 l_age 这样的 C 风格前缀吗?

I am developing a CLS-compliant types library and I have a class inside It, which contains private, protected and public fields and properties. I use underscore symbol (_) as prefix for private or protected fields and little first letter to distinct their from properties with same names. It looks so:

class SomeClass
{
private int _age; //Here is OK

public int Age { get { return this._get; } }
}

But when I try to use protected fields I collide with a next problem:

class SomeClass
{
protected int _age; //Here is NOT CLS-compliant (because of _ can't be the first symbol of identifier)

public int Age { get { return this._get; } }
}

Then I tried to do in such way:

class SomeClass
{
protected int age; //Here is NOT CLS-compliant (because of age and Age differ only in one symbol)

public int Age { get { return this._get; } }
}

Please, tell me, what is right CLS-compliant notation or convention between developers for such cases? Have I to use prefixes in C-style like l_age?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

z祗昰~ 2024-12-13 11:04:14

这是一个更正确的版本,IMO:

private int _age;
public int Age {
    get { return this._age ; }
    protected set { this._age = value; }
}

或者简单地说:

public int Age { get; protected set; }

如果您正确封装它,那么该字段的名称​​并不重要,因为该类型之外的没有任何东西可以看到它。


在评论中,然后提出了事件的问题,例如:

protected EventHandler<StateChangedEventArgs> _stateChanged;
public event EventHandler<StateChangedEventArgs> StateChanged
{
    add { lock (this.StateChanged) { this._stateChanged += value; } }
    remove { lock (this.StateChanged) { this._stateChanged -= value; } }
}

这里我再次断言,没有理由保护该字段;该事件不属于派生类。它有 2 个需要执行的合理操作:

  1. 调用事件
  2. 订阅/取消订阅事件

前者应该通过 On* 模式完成;后者应该只使用常规访问器(否则它会违反锁定)。另外,即使我们假设lock(this.StateChanged)是一个拼写错误(这将是一个非常非常糟糕的事情,用作锁定对象 -it 根本不起作用),请注意,在 C# 4.0 中,编译器内置了更高效的锁定策略(使用 Interlocked 而不是 监视)当你写一个“类似字段”事件(即没有明确的添加/删除)。因此,这里的首选方法是:

public event EventHandler<StateChangedEventArgs> StateChanged;
protected virtual void OnStateChanged(StateChangedEventArgs args) {
    var snapshot = StateChanged; // avoid thread-race condition
    if(snapshot != null) shapshot(this, args);
}

并且......就是这样!

  • 如果子类想要订阅/取消订阅(不理想,但没什么),它只需使用 StateChanged +=StateChanged -=
  • 如果子类想要调用事件,它会调用OnStateChanged(...)
  • 如果子类想要调整事件逻辑,它会向 OnStateChanged 添加一个覆盖

不需要任何非私有的字段。

Here's a more correct version, IMO:

private int _age;
public int Age {
    get { return this._age ; }
    protected set { this._age = value; }
}

or simply:

public int Age { get; protected set; }

If you properly encapsulate it, then it doesn't matter what the field is called, as nothing outside that type can see it.


In comments, the question of events is then raised, with the example:

protected EventHandler<StateChangedEventArgs> _stateChanged;
public event EventHandler<StateChangedEventArgs> StateChanged
{
    add { lock (this.StateChanged) { this._stateChanged += value; } }
    remove { lock (this.StateChanged) { this._stateChanged -= value; } }
}

Here I again assert that there is no reason for this field to be protected; the event does not belong to the derived class. It has 2 sensible operations it can want to perform:

  1. invoke the event
  2. subscribe/unsubscribe to the event

The former should be done via the On* pattern; the latter should just use the regular accessors (otherwise it violates the lock). Also, even if we assume that lock(this.StateChanged) is a typo (that would be a really, really bad thing to use as the lock object -it would not work at all), note that in C# 4.0 the compiler has a much more efficient lock strategy inbuilt (that uses Interlocked rather than Monitor) when you write a "field-like" event (i.e. no explicit add/remove). Consequently, the preferred approach here would be:

public event EventHandler<StateChangedEventArgs> StateChanged;
protected virtual void OnStateChanged(StateChangedEventArgs args) {
    var snapshot = StateChanged; // avoid thread-race condition
    if(snapshot != null) shapshot(this, args);
}

and... that's it!

  • if the subclass wants to subscribe/unsubscribe (not ideal, but meh) it just uses StateChanged += and StateChanged -=
  • if the subclass wants to invoke the event, it calls OnStateChanged(...)
  • if the subclass wants to tweak the event logic, it adds an override to OnStateChanged

no need for any non-private fields.

錯遇了你 2024-12-13 11:04:14

为了支持 Marc 的回答,Microsoft 的字段设计指南指出:

公共和受保护字段的版本控制不佳,并且不受代码访问安全要求的保护。不要使用公开可见的字段,而是使用私有字段并通过属性公开它们。

这可能就是为什么您找不到任何有关命名它们的有用指导(事实上,命名指南只需返回“字段设计”页面即可)。

To back up Marc's answer, the guidance on Field Design from Microsoft states:

Public and protected fields do not version well and are not protected by code access security demands. Instead of using publicly visible fields, use private fields and expose them through properties.

This is probably why you will not find any useful guidance on naming them (in fact, the naming guidelines just point back at the Field Design page).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文