属性 Property

作者:张齐天
链接:https://www.zhihu.com/question/410257728/answer/1375205727
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Part 1 封装啊,少年!

属性最早是没有简化写法的。最开始属性是写作

private int _a; // field.
public int A // property corresponding to the field '_a'.
{
    get { return _a; }
    set { _a = value; }
}

的。首先,这个写法有一个好处,它可以避免和防止对 _a 乱赋值,因为我们可以为 set 块里添加数据处理逻辑,比如数据验证逻辑。假设这个 A 表示一个人的年龄,那么我们至少可以知道,年龄是不可能低于 0 的(至于多大,暂时设置个 150 吧)。那么处理逻辑可以改写成这样:

private int _a;
public int A
{
    get { return _a; }
    set
    {
        if (value < 0 || value > 150)
             throw new ArgumentException("The value is out of range.", nameof(value));

        _a = value;
    }
} 

于是,这样就避免了其他程序员使用字段的时候,为其随意赋值的情况。大多数情况,这样比起直接一个 public 的字段要好。OOP 的本质就是封装。
如果你不把字段封装起来,你自己知道怎么用,那你平时肯定没啥问题,只是别人看到你的代码,可以随便找到“漏洞”。

Part 2 自动属性?

然后来说一下这个:自动属性。
自动属性是 C# 3 才有的一种规定写法。要是一个单纯的 getset 块,那么可以简写:public int A { get; set; }
那么问题来了。这玩意儿都没有任何数据校验的操作了,请问这个跟一个 public 字段又有什么区别呢?你忽略了一点。自动属性是可以在 setget 块的前面放一个访问修饰符的。
比如,我们可以让 A 属性只能在当前类里面才可以随意赋值,此时我们可以为 set 块添加 private 修饰:public int A { get; private set; }
这样,数据 A 就不能在外面随便赋值了。另外,这么写不等于 private _a 字段声明。因为 A 的值是可以在类外面的任何位置用到,只是无法修改,所以单纯的 private _apublic A { get; private set; }并不等价。

Part 3 属性还有别的好处吗?

前面已经说到了一些好处,这里再说一个。属性是一个包装器,它包含两个方法,get 和 set。这两个方法类比 Java 其实就知道它只是 getxxx() 和 setxxx(int value) 的简化写法而已。
既然是两个方法,那么执行操作就是不占内存空间的。说白了,在不多出任何内存的时候就可以为类的字段添加处理逻辑,这是不是一个很有趣的行为呢?
实际上,我们的这些代码是有一个专门存放代码的内存区域,叫做代码区。但它们和我们知道的栈内存和堆内存是完全分开的。我说它不占内存是因为,它并不影响这个类型的存储空间。

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
public struct C
{
    [field: FieldOffset(0)]
    public int A { get; set; }
}

public static class Program
{
    private static void Main() => Console.WriteLine(Marshal.SizeOf<C>());
}

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
public struct C
{
    [FieldOffset(0)]
    private int _a;
}

public static class Program
{
    private static void Main() => Console.WriteLine(Marshal.SizeOf<C>());
}

都是占据 4 个字节

posted @ 2024-04-08 10:48  njit-sam  阅读(2)  评论(0编辑  收藏  举报