为什么我会使用自动实现而不是封装?

时间:2018-06-16 05:02:41

标签: c# private encapsulation public

private int someInt;

public int GetSomeInt()
{
    return someInt;
}

我何时会使用上面的代码而不是以下代码?

public int SomeInt { get; set; }

我被告知总是封装所有变量,而不是将它们声明为公共变量,而自动实现似乎只是这样做。

当字段被声明为public时,这是否会使封装的目的无效?

3 个答案:

答案 0 :(得分:6)

自动实现只是封装字段的语法糖,因为除了设置或检索字段值之外,不需要额外的逻辑。它不会取代封装,它只是为了节省时间和击键。您自己的代码无法访问自动实现的属性的支持字段 - 所有可见的属性。此属性及其访问器可以具有字段可以具有的任何相同的访问修饰符。

与私有支持字段相比,更准确的自动实现等效内容包含私有设置器:

public int SomeInt { get; private set; }

答案 1 :(得分:2)

  

我何时会使用上面的代码而不是以下代码?

当您通过括号付款时? :-)

请记住代码

public int SomeInt { get; set; }

是等同于

的简写
private int someInt;

public int SomeInt
{
   get { return someInt; }
   set { someInt = value; }
}

因此,您可以想象放入GetSomeInt方法的任何逻辑也可以放在SomeInt属性的'getter'(或'setter')中。

在可能的情况下,您应该使用public int SomeInt { get; set; }语法,因为它会立即提醒读者您所拥有的是一个可以设置或访问的简单属性,而无需理解任何其他逻辑。

如果get或set逻辑更复杂,则可以使用更长形式的属性定义。

尽管我对括号进行了讽刺性评论,但Property Design的框架设计指南建议

  

如果getter可以抛出异常,则应该将其重新设计为方法。请注意,此规则不适用于索引器,因为我们确实会在验证参数时遇到异常。

因此,这可能是您可能实现GetSomeInt而不是SomeInt属性获取器的情况的一个示例。

答案 2 :(得分:1)

以下代码是合成糖类的东西。

public int MyValue { get; set; }

如果你看一下之后生成的IL(MSIL)代码,你就会意识到编译器实际在做什么。

.class public auto ansi beforefieldinit ConsoleApplication3.Sample
    extends [mscorlib]System.Object
{
    // Fields
    .field private int32 '<MyValue>k__BackingField'
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
        01 00 00 00 00 00 00 00
    )

    // Methods
    .method public hidebysig specialname 
        instance int32 get_MyValue () cil managed 
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x205c
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldfld int32 ConsoleApplication3.Sample::'<MyValue>k__BackingField'
        IL_0006: ret
    } // end of method Sample::get_MyValue

    .method public hidebysig specialname 
        instance void set_MyValue (
            int32 'value'
        ) cil managed 
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2064
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldarg.1
        IL_0002: stfld int32 ConsoleApplication3.Sample::'<MyValue>k__BackingField'
        IL_0007: ret
    } // end of method Sample::set_MyValue

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2053
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method Sample::.ctor

    // Properties
    .property instance int32 MyValue()
    {
        .get instance int32 ConsoleApplication3.Sample::get_MyValue()
        .set instance void ConsoleApplication3.Sample::set_MyValue(int32)
    }

} // end of class ConsoleApplication3.Sample

在上面的代码编译器中自动生成私有字段。

.field private int32 '<MyValue>k__BackingField'

所以仍然是私人领域,财产是公开的。您可以为get和set指定访问修饰符以控制属性访问级别。