为什么我要使用自动实现而不是封装?
Why would I use auto-implementation over encapsulation?
private int someInt;
public int GetSomeInt()
{
return someInt;
}
我什么时候会在下面的代码上使用上面的代码?
public int SomeInt { get; set; }
有人告诉我 总是 封装 所有 变量而不是将它们声明为 public,并自动执行似乎就是这么做的。
声明字段时,这不会使封装的目的无效吗public?
以下代码是合成糖之类的东西。
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'
所以字段仍然是私有的,属性 是 public。您还可以为 get 和 set 指定访问修饰符以控制 属性 访问级别。
自动实现只是封装字段的语法糖,适用于除了设置或检索字段值之外不需要其他逻辑的情况。它不会取代封装,只是为了节省时间和击键次数。您自己的代码无法访问自动实现的 属性 的支持字段——可见的只有 属性。此 属性 及其访问器可以具有字段可以具有的任何相同访问修饰符。
一个更准确的自动实现的等同于你拥有的东西,有一个私有支持字段,包含一个私有 setter:
public int SomeInt { get; private set; }
When would I use the above code over the below code?
你什么时候按括号付钱的? :-)
记住密码
public int SomeInt { get; set; }
是 shorthand 相当于
private int someInt;
public int SomeInt
{
get { return someInt; }
set { someInt = value; }
}
因此,您可以想象在 GetSomeInt
方法中放入的任何逻辑也可以在 'getter'(或 'setter')中放入 SomeInt
属性.
在可能的情况下,您应该使用 public int SomeInt { get; set; }
语法,因为它会立即提醒 reader 您所拥有的是一个简单的 属性,无需任何进一步的逻辑即可设置或访问被理解。
如果获取或设置逻辑更复杂,则可以使用更长形式的 属性 定义。
尽管我对括号的评论很滑稽,Property Design 的框架设计指南建议
If a getter can throw an exception, it should probably be redesigned to be a method. Notice that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.
因此,这将是您可以实施 GetSomeInt
而不是 SomeInt
属性 getter.
的情况的一个示例
private int someInt;
public int GetSomeInt()
{
return someInt;
}
我什么时候会在下面的代码上使用上面的代码?
public int SomeInt { get; set; }
有人告诉我 总是 封装 所有 变量而不是将它们声明为 public,并自动执行似乎就是这么做的。
声明字段时,这不会使封装的目的无效吗public?
以下代码是合成糖之类的东西。
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'
所以字段仍然是私有的,属性 是 public。您还可以为 get 和 set 指定访问修饰符以控制 属性 访问级别。
自动实现只是封装字段的语法糖,适用于除了设置或检索字段值之外不需要其他逻辑的情况。它不会取代封装,只是为了节省时间和击键次数。您自己的代码无法访问自动实现的 属性 的支持字段——可见的只有 属性。此 属性 及其访问器可以具有字段可以具有的任何相同访问修饰符。
一个更准确的自动实现的等同于你拥有的东西,有一个私有支持字段,包含一个私有 setter:
public int SomeInt { get; private set; }
When would I use the above code over the below code?
你什么时候按括号付钱的? :-)
记住密码
public int SomeInt { get; set; }
是 shorthand 相当于
private int someInt;
public int SomeInt
{
get { return someInt; }
set { someInt = value; }
}
因此,您可以想象在 GetSomeInt
方法中放入的任何逻辑也可以在 'getter'(或 'setter')中放入 SomeInt
属性.
在可能的情况下,您应该使用 public int SomeInt { get; set; }
语法,因为它会立即提醒 reader 您所拥有的是一个简单的 属性,无需任何进一步的逻辑即可设置或访问被理解。
如果获取或设置逻辑更复杂,则可以使用更长形式的 属性 定义。
尽管我对括号的评论很滑稽,Property Design 的框架设计指南建议
If a getter can throw an exception, it should probably be redesigned to be a method. Notice that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.
因此,这将是您可以实施 GetSomeInt
而不是 SomeInt
属性 getter.