Ken*_*Ken 5 c# standards coding-style properties
我看过一些代码并认为它似乎有问题,所以我想知道它是否可以用于良好的编码,我的第一个想法是不。
考虑:
class MyClass
{
private string m_MySuperString;
public string MySuperString
{
get { return m_MySuperString; }
set { m_MySuperString = value; }
}
public void MyMethod()
{
if (blah != yada)
{
m_MySuperString = badabing;
}
}
public void MyOtherMethod()
{
if (blah == yada)
{
m_MySuperString = badaboom;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种对支持字段的直接访问是一种可以接受的做法还是糟糕的编码 - 或者我应该问一下属性访问器的意义是什么,如果这是在具有公共成员的类中内部完成的,则访问被多个允许组件 - 是否可能发生崩溃 - 我会在多线程应用程序中冒险应该会发生崩溃。
请问有什么想法吗?我已经看过这个关于 SO 和其他人的链接> 为什么使用私有成员然后使用公共属性来设置它们?
编辑
让我说清楚,因为提供了很好的信息,而不是直接回复所有答案和评论。我不是在问属性的用途,也不是我是否可以执行自动实现的属性、私有设置器、OnValueChange 通知、属性逻辑。我的问题是关于直接访问该支持字段 - 例如,如果您说的是多线程场景 - 不是 getter/setter 同步锁的全部重点 - 控制对 backingfield 的访问?在这种情况下,这种代码是否可以接受 - 只需向 getter 和 setter 添加一个同步锁?请记住 myClass 的构造函数中的代码是一个示例 - 代码可以在任何附加方法中 - 例如更新的类 - Method1
结束编辑
我建议查看 @JonSkeet 的 C# In Depth 的第 8 章第 1 节(出于教育目的,我无耻地从中摘取了以下代码片段),以获取有关自动实现的属性的更多信息。简而言之,回答你的问题,不,这段代码没有任何问题。
考虑以下片段:
public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)
被编译为
private string <Name>k__BackingField;
public string Name
{
get { return <Name>k__BackingField; }
set { <Name>k__BackingField = value; }
}
Run Code Online (Sandbox Code Playgroud)
...所以编译器已经为您完成了上面完成的工作。有多种方法可以修改它正在执行的操作,但这些方法并不能真正回答问题。书中给出的关于线程安全的一个例子是这样的:
//code above, plus
private static int InstanceCounter { get; set; }
private static readonly object counterLock = new object();
public InstanceCountingPerson(string name, int age) {
Name = name;
Age = age;
lock (counterLock) // safe property access
{
InstanceCounter++;
// and whatever else you have to do with the lock enabled
}
}
Run Code Online (Sandbox Code Playgroud)
- 这也是这个 SO 问题中引用的模式。然而,正如那里所指出的,锁(a)可能很慢,(b)实际上可能无法确保其工作完成,因为它们必须在某个时刻被释放,以及(c)依赖信任系统,因为它们有点天真地假设任何想要访问该对象的东西都会正确使用锁(并不总是正确的,至少在我见过的一些代码中不是这样:D)。getter 和 setter 方法的优点是您可以对类的任何实例强制使用锁的模式(阅读:正确封装字段,正如其他人所建议的那样)。
然而,您可能会考虑的另一种模式是控制反转。使用依赖注入容器,您可以指定您满意的线程安全级别。如果您对每个人都等待对象的单例实例感到满意,则可以声明对该对象接口的所有引用都引用同一对象(并且必须等待该对象变得可用),或者您可以确定线程安全每次请求时都应创建该对象的实例。有关更多详细信息,请参阅此 SO 答案。
笔记:
对上述想法的任何经过同行评审的批评都将被慷慨地接受并添加到答案中,因为我目前是一个线程安全外行。