对于一个字段的简单接口,这些选项之间有什么区别?

本文关键字:之间 选项 什么 区别 字段 于一个 简单 接口 | 更新日期: 2023-09-27 18:13:39

我只是盯着下面的代码,想知道是否真的有必要填满12行源代码。

    private static IUnityContainer _container;
    public static IUnityContainer Container
    {
        get
        {
            return _container;
        }
        set
        {
            _container = value;
        }
    }

我的想法是,为什么不只有一个?

    public static IUnityContainer Container;

我认为答案是类似于"你不能打破封装"…这更多的是对条件反射的膝跳反应,还是有其他的原因,微妙的或其他的?

对于一个字段的简单接口,这些选项之间有什么区别?

除非您不想以某些奇怪的方式(如GetType())使用反射。GetProperty("Container"…)没有缺点

然而,暴露字段被认为是不干净的,从纯粹主义者的角度来看,属性通常是干净的。

FxCop会警告你这不是一件好事,但也没有缺点。

如果你想同时保持简洁,你可以使用自动属性:

public static IUnityContainer Container { get; set; }

自动属性只在编译器3.0版本起作用。

可能发生的缺点是,如果您或某人在某些函数中通过ref传递该字段,例如Interlocked.Exchange(ref MyClass.MyStaticField, null);如果将来用属性更改它,它将不再工作,因此您应该小心不要通过引用传递该字段。如果你从一开始就使用一个属性,你就不会有这个问题。static readonly字段不会出现这个问题,它们不能通过引用传递。使用静态只读字段是很常见的。

当你有一个类继承了用于远程处理(RPC,远程过程调用)的MarshalByRefObject时,绝对不应该使用字段来代替属性。

我在这里发布了一个例子,正如我所说,这不是你的情况,因为问题是与实例字段,而不是与静态字段。

public class MyClass :
    MarshalByRefObject
{
    public int MyValue;
}
class Program
{
    static void Main(string[] args)
    {
        var obj = new MyClass();
        // This will give you warning CS1690: Accessing a member on 'MyValue' may cause a runtime exception because it is a field of a marshal-by-reference class
        Console.WriteLine(obj.MyValue.ToString());
    }
}

远程过程调用只能与方法和属性一起工作,因此编译器会给你一个警告,因为MarshalByRefObject可以在另一个AppDomain中调用,也可以由另一个进程或另一台计算机通过TCP/IP调用。

我个人是这样认为的。假设在稍后的某个时间,我想建立一个不变式,即"容器"永远不会为空。如果它被定义为公共字段,那么强制执行的方法是找出使用它的每个客户端,并放入代码以防止它被设置为null。如果我把它作为一个属性,同样的事情也可以像这样完成:

private static IUnityContainer _container = new ContainerImpl();
public static IUnityContainer Container
{
    get
    {
        return _container;
    }
    set
    {
        _container = value ?? _container;
    }
}

或者,您可以对空值抛出异常,以便更有表现力。具体细节并不重要,重要的是封装角度。

所以,我认为这不是一个简单的下意识的反应,而是一个实用和合理的,特别是面对静态关键字。如果没有封装,它实际上只是一个全局变量。至少封装全局状态允许提供者对其进行某种表面上的控制,而不是在整个应用程序中泄漏控制,并信任/强制客户端保持一致。

有人可能会认为这是"不要重复自己"的问题。当涉及到一个字段时,任何公共逻辑都必须在所有地方复制。