声明 属性 的最佳方式是什么
what the best way to declare a property
我正在从 Objective-C 切换到 C# 以开始使用 Unity 引擎。所以我试图吸收所有 C# 差异。 Obj-C 具有自动创建 getter 和 setter 的 @synthesize。老实说,它们对我来说有点陌生。在 Obj-C 中我经常这样做:
@synthesize myProperty = _myProperty;
然后在本地 class 代码中使用 _myProperty
并使用 myProperty
访问此 class 之外的 属性。或者更准确地说 classInstance.myProperty
.
此外,在 Obj-C 中,您可以将 属性 声明为 readonly
,而不必担心意外更改它在 class.
之外的值
在 C# 中,我试图编写适当的面向对象的代码,但我为此苦苦挣扎。我本质上是一名 C 编码员,并且很乐意随处访问所有内容,我知道这是不好的和不必要的。我也不想向 GameObject Inspector 公开大量属性。我更喜欢尽可能多地以编程方式进行。
那么声明属性的最佳方式是什么,这样我就可以从另一个 class 访问它们,而且它们不会暴露在 Inspector 中?以下是我遇到和使用过的一些可能性:
// 1. public static - public without being exposed in inspector
public static int myProperty;
// 2. the public _text doesn't appear in the inspector but the text one does.
public string _text;
public string text {
get { return _text; }
set {
_text = value;
}
}
// 3. private _underscore version with no setter - does removing the set make it read only?
private float _current;
public float current {
get { return _current; }
}
// 4. creating my own getter function
private int myValue;
...
int GetMyValue() {
return myValue;
}
另外.. 我在某处读到,在 .NET 中你不应该在 属性 名称中使用下划线。我真的不知道 属性 的下划线版本是做什么的或代表什么。我认为在 Obj-C 中它会影响范围,但我真的不知道。
我在调用变量属性时是否正确?
有人建议生成这个的 prop tab tab:
public object MyProperty {
get;
set;
}
不幸的是,这并没有真正回答我关于只读的问题。 int 或 string 甚至是对象吗?它不在 Obj-C 中。
创建属性的正确方法实际上取决于您要实现的目标。如果您只想创建一个 属性 以供进一步使用,您可以创建 shorthand 方式:
public object MyProperty { get; set; }
如果需要更多功能,您可以添加额外的功能,例如:
private int _myInt;
public int MyInt {
get { return this._name; }
set {
if (this._name == 1) {
this._name = value;
} else {
this._name = 0;
}
}
}
您问题的答案完全取决于您希望实现的目标,两种方式都可以接受。
getter 和 setter 方法的使用,例如 Java 中的方法,在 C# 中是不受欢迎的。
为了回答你的另一个问题,String 是 C# 中的一个对象。 int 是原始类型。
这里是您遇到的问题的简要总结。
在 C# 中有一个所谓的 snippet
可以让您快速生成代码。它的快捷方式是输入 prop
,然后按 Tab 键,这会生成类似这样的代码。
public int MyProperty { get; set; }
现在,如果您要创建字段,并且不想将其公开给实例。你应该做到 private
.
例子
private int myVar; // private is not exposed on instances only public properties are
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
现在对于 static
字段,static
fields/properties 是类型可访问的。所以要隐藏它们,你只需要让它们 private
例子
private static bool myProp; // can't be accessed on the Program Type
public static bool MyProp { get; set; } // can be accessed on the Program Type
class MyClass
{
public MyClass()
{
Program.MyProp = true;
Program.myProp= true; // wont build
}
}
如果你想让它只读并且防止修改,你可以这样做。
public int MyProperty { get; private set; } // can get but not set
private int myVar;
public int MyProperty
{
get { return myVar; } // same as the top but with a field
}
为了更深入、更好地理解,请阅读 What are Access Modifiers in C#?
NonSerialized 和 HideInspector 属性是您必须考虑从 Unity 检查器隐藏 class 成员的两个选项。 NonSerialized 不是 Unity 特有的,HideInspector 是 Unity 特有的。 Unity 在编译后的代码中查找这两个属性以确定在检查器中公开的内容。
如果你想要一个 publicly 只读 属性 你可以这样声明它...
[System.NonSerialized]
private string _text;
/// <summary>
/// Gets the Text
/// </summary>
/// <remarks>May be set within this class or derived classes</remarks>
public string Text {
get { return _text; }
protected set {
_text = value;
}
}
您似乎对访问修饰符的含义有疑问...
查看此页面...
https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
简要...
- public = 可从任何地方访问,不要将属性的支持变量声明为 public,否则人们可以简单地跳过您的 属性 访问器。
- protected = 在您的 class 和继承 class
的 classes 中可访问
- 内部 = 在同一程序集中可访问
- protected internal = 在同一个程序集中可访问
classes 继承了 class
- 私有 = 只能在您的 class
内访问
您只需声明
即可取消支持变量
/// <summary>
/// Gets or sets the Text
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets the current
/// </summary>
public float Current { get; protected set; }
自 auto-implemented variables 出现以来,没有任何技术原因需要使用支持变量创建属性,除非您有额外的逻辑希望在 get and/or 集上执行。
例如,您想要创建在 属性 更改时引发事件的 Observable 实体...
private int _id;
public int ID
{
get
{
return _id;
}
set
{
if (_id != value)
{
OnIDChanging(value);
ReportPropertyChanging("ID");
_id = StructuralObject.SetValidValue(value);
ReportPropertyChanged("ID");
OnIDChanged();
}
}
}
关于编码标准,网上有很多。我会推荐 IDesign 的...
http://www.idesign.net/downloads/getdownload/1985
您会注意到我更改了您发布的代码的大小写,我使用的大小写符合 IDesign 的命名准则
Public 变量(不是字段)显示在 Unity 检查器中。如果你想隐藏一个public变量,你可以在它前面加上NonSerialized,像这样:
[System.NonSerialized]
public bool m_HideWhenInactive = false;
您也可以通过将其设为 属性 来完全避免此问题。检查器中未显示任何属性:
public bool m_HideWhenInactive { get; set; }
作为一个有趣的奖励(我知道这不是你的问题),你可以有一个 属性 世界阅读,私人写的:
public bool m_HideWhenInactive { get; private set; }
最后,如果您确实希望将变量序列化并存储在预制件中,但又不想让设计师对其进行编辑(如果您打算编写自定义编辑器 class),那么一个不同的注释:
[HideInInspector]
public bool m_HideWhenInactive = false;
检查器中永远不会显示静态字段。
Unity 引擎上下文中的 属性 模式往往与 C# 的 'norm' 略有不同,因为您通常对在编辑器中制作可调整数据感兴趣。这意味着序列化。
- Unity 无法序列化属性
- Unity 可以序列化原始类型的字段和继承自 UnityEngine.Object 的类型是序列化引用
- Unity也可以序列化上述类型的列表和数组
- MonoBehaviours 上的序列化字段在编辑器中公开并且可以编辑
- public 字段默认序列化,如果用 [SerializeField] 属性标记则为私有字段。
- 如果 class 是 MonoBehavior
上的字段,Unity 也会序列化 class 上标有 [System.Serializable] 的字段
有关更深入的讨论,请参阅:https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
以下模式是通用的,backing field 可以由开发者设置,不需要重新编译,并且在运行-time 不能被外部代码更改。
[SerializeField]
private int editableInEditor;
public int NotEditableInEditor
{
get { return editableInEditor; }
}
这个模式也是,懒惰-getter。
private DerivedMonoBehaviour component;
public DerivedMonoBehaviour Component
{
get
{
if(component == null)
{
// Note: Using the null-coalescing operator ??
// is inadvisable when dealing with UnityEngine.Object
// references.
// See: https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/
component = GetComponent<DerivedMonoBehaviour>();
}
return component;
}
}
我正在从 Objective-C 切换到 C# 以开始使用 Unity 引擎。所以我试图吸收所有 C# 差异。 Obj-C 具有自动创建 getter 和 setter 的 @synthesize。老实说,它们对我来说有点陌生。在 Obj-C 中我经常这样做:
@synthesize myProperty = _myProperty;
然后在本地 class 代码中使用 _myProperty
并使用 myProperty
访问此 class 之外的 属性。或者更准确地说 classInstance.myProperty
.
此外,在 Obj-C 中,您可以将 属性 声明为 readonly
,而不必担心意外更改它在 class.
在 C# 中,我试图编写适当的面向对象的代码,但我为此苦苦挣扎。我本质上是一名 C 编码员,并且很乐意随处访问所有内容,我知道这是不好的和不必要的。我也不想向 GameObject Inspector 公开大量属性。我更喜欢尽可能多地以编程方式进行。
那么声明属性的最佳方式是什么,这样我就可以从另一个 class 访问它们,而且它们不会暴露在 Inspector 中?以下是我遇到和使用过的一些可能性:
// 1. public static - public without being exposed in inspector
public static int myProperty;
// 2. the public _text doesn't appear in the inspector but the text one does.
public string _text;
public string text {
get { return _text; }
set {
_text = value;
}
}
// 3. private _underscore version with no setter - does removing the set make it read only?
private float _current;
public float current {
get { return _current; }
}
// 4. creating my own getter function
private int myValue;
...
int GetMyValue() {
return myValue;
}
另外.. 我在某处读到,在 .NET 中你不应该在 属性 名称中使用下划线。我真的不知道 属性 的下划线版本是做什么的或代表什么。我认为在 Obj-C 中它会影响范围,但我真的不知道。
我在调用变量属性时是否正确?
有人建议生成这个的 prop tab tab:
public object MyProperty {
get;
set;
}
不幸的是,这并没有真正回答我关于只读的问题。 int 或 string 甚至是对象吗?它不在 Obj-C 中。
创建属性的正确方法实际上取决于您要实现的目标。如果您只想创建一个 属性 以供进一步使用,您可以创建 shorthand 方式:
public object MyProperty { get; set; }
如果需要更多功能,您可以添加额外的功能,例如:
private int _myInt;
public int MyInt {
get { return this._name; }
set {
if (this._name == 1) {
this._name = value;
} else {
this._name = 0;
}
}
}
您问题的答案完全取决于您希望实现的目标,两种方式都可以接受。
getter 和 setter 方法的使用,例如 Java 中的方法,在 C# 中是不受欢迎的。
为了回答你的另一个问题,String 是 C# 中的一个对象。 int 是原始类型。
这里是您遇到的问题的简要总结。
在 C# 中有一个所谓的 snippet
可以让您快速生成代码。它的快捷方式是输入 prop
,然后按 Tab 键,这会生成类似这样的代码。
public int MyProperty { get; set; }
现在,如果您要创建字段,并且不想将其公开给实例。你应该做到 private
.
例子
private int myVar; // private is not exposed on instances only public properties are
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
现在对于 static
字段,static
fields/properties 是类型可访问的。所以要隐藏它们,你只需要让它们 private
例子
private static bool myProp; // can't be accessed on the Program Type
public static bool MyProp { get; set; } // can be accessed on the Program Type
class MyClass
{
public MyClass()
{
Program.MyProp = true;
Program.myProp= true; // wont build
}
}
如果你想让它只读并且防止修改,你可以这样做。
public int MyProperty { get; private set; } // can get but not set
private int myVar;
public int MyProperty
{
get { return myVar; } // same as the top but with a field
}
为了更深入、更好地理解,请阅读 What are Access Modifiers in C#?
NonSerialized 和 HideInspector 属性是您必须考虑从 Unity 检查器隐藏 class 成员的两个选项。 NonSerialized 不是 Unity 特有的,HideInspector 是 Unity 特有的。 Unity 在编译后的代码中查找这两个属性以确定在检查器中公开的内容。
如果你想要一个 publicly 只读 属性 你可以这样声明它...
[System.NonSerialized]
private string _text;
/// <summary>
/// Gets the Text
/// </summary>
/// <remarks>May be set within this class or derived classes</remarks>
public string Text {
get { return _text; }
protected set {
_text = value;
}
}
您似乎对访问修饰符的含义有疑问...
查看此页面...
https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
简要...
- public = 可从任何地方访问,不要将属性的支持变量声明为 public,否则人们可以简单地跳过您的 属性 访问器。
- protected = 在您的 class 和继承 class 的 classes 中可访问
- 内部 = 在同一程序集中可访问
- protected internal = 在同一个程序集中可访问 classes 继承了 class
- 私有 = 只能在您的 class 内访问
您只需声明
即可取消支持变量/// <summary>
/// Gets or sets the Text
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets the current
/// </summary>
public float Current { get; protected set; }
自 auto-implemented variables 出现以来,没有任何技术原因需要使用支持变量创建属性,除非您有额外的逻辑希望在 get and/or 集上执行。
例如,您想要创建在 属性 更改时引发事件的 Observable 实体...
private int _id;
public int ID
{
get
{
return _id;
}
set
{
if (_id != value)
{
OnIDChanging(value);
ReportPropertyChanging("ID");
_id = StructuralObject.SetValidValue(value);
ReportPropertyChanged("ID");
OnIDChanged();
}
}
}
关于编码标准,网上有很多。我会推荐 IDesign 的...
http://www.idesign.net/downloads/getdownload/1985
您会注意到我更改了您发布的代码的大小写,我使用的大小写符合 IDesign 的命名准则
Public 变量(不是字段)显示在 Unity 检查器中。如果你想隐藏一个public变量,你可以在它前面加上NonSerialized,像这样:
[System.NonSerialized]
public bool m_HideWhenInactive = false;
您也可以通过将其设为 属性 来完全避免此问题。检查器中未显示任何属性:
public bool m_HideWhenInactive { get; set; }
作为一个有趣的奖励(我知道这不是你的问题),你可以有一个 属性 世界阅读,私人写的:
public bool m_HideWhenInactive { get; private set; }
最后,如果您确实希望将变量序列化并存储在预制件中,但又不想让设计师对其进行编辑(如果您打算编写自定义编辑器 class),那么一个不同的注释:
[HideInInspector]
public bool m_HideWhenInactive = false;
检查器中永远不会显示静态字段。
属性 模式往往与 C# 的 'norm' 略有不同,因为您通常对在编辑器中制作可调整数据感兴趣。这意味着序列化。
- Unity 无法序列化属性
- Unity 可以序列化原始类型的字段和继承自 UnityEngine.Object 的类型是序列化引用
- Unity也可以序列化上述类型的列表和数组
- MonoBehaviours 上的序列化字段在编辑器中公开并且可以编辑
- public 字段默认序列化,如果用 [SerializeField] 属性标记则为私有字段。
- 如果 class 是 MonoBehavior 上的字段,Unity 也会序列化 class 上标有 [System.Serializable] 的字段
有关更深入的讨论,请参阅:https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
以下模式是通用的,backing field 可以由开发者设置,不需要重新编译,并且在运行-time 不能被外部代码更改。
[SerializeField]
private int editableInEditor;
public int NotEditableInEditor
{
get { return editableInEditor; }
}
这个模式也是,懒惰-getter。
private DerivedMonoBehaviour component;
public DerivedMonoBehaviour Component
{
get
{
if(component == null)
{
// Note: Using the null-coalescing operator ??
// is inadvisable when dealing with UnityEngine.Object
// references.
// See: https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/
component = GetComponent<DerivedMonoBehaviour>();
}
return component;
}
}