我从Objective-C切换到C#以开始使用Unity引擎。所以我试图沉浸在所有的C#差异中。 Obj-C有@synthesize,自动创建getter和setter。说实话,他们对我来说很新鲜。在Obj-C中,我经常这样做:
@synthesize myProperty = _myProperty;
然后使用本地类代码中的_myProperty
并使用myProperty
访问此类之外的该属性。或者更准确classInstance.myProperty
。
同样在Obj-C中,您可以将属性声明为readonly
,而不必担心在课堂外意外更改它的值。
在C#中,我试图编写适当的面向对象的代码,我很挣扎。我是一名C级编码员,我很乐意随处访问所有内容,我知道这是不好的和不必要的。我也不想向GameObject Inspector公开大量的属性。我更喜欢尽可能以编程方式进行操作。
那么声明属性的最佳方法是什么,以便我可以从另一个类访问它们,但是它们也不会在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中影响了范围,但并不是真的知道。
我甚至在调用变量属性时是否正确?
有人提出了支持选项卡标签,它产生了这个:
public object MyProperty {
get;
set;
}
不幸的是,这并没有真正回答我关于只读的问题。是一个int或字符串甚至是一个对象?它不在Obj-C中。
答案 0 :(得分:2)
公共变量(非字段)显示在Unity检查器中。如果要隐藏公共变量,可以使用NonSerialized作为前缀,如下所示:
[System.NonSerialized]
public bool m_HideWhenInactive = false;
您也可以通过将其作为属性来完全避免此问题。检查员中未显示任何属性:
public bool m_HideWhenInactive { get; set; }
作为一个有趣的奖励(不是你的问题,我知道),你可以拥有一个世界读物,私人写的财产:
public bool m_HideWhenInactive { get; private set; }
最后,如果您想要将变量序列化并存储在预制件中,但您不希望设计人员对其进行编辑(如果您打算编写自定义编辑器类),则会有不同的注释:
[HideInInspector]
public bool m_HideWhenInactive = false;
静态字段永远不会显示在检查器中。
答案 1 :(得分:1)
NonSerialized和HideInspector属性是您必须考虑从Unity检查器隐藏类成员的两个选项。 NonSerialized并非特定于Unity,HideInspector特定于Unity。 Unity在编译的代码中查找这两个属性,以确定在检查器中公开的内容。
如果你想要一个只读的公共财产,你可以这样声明......
[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
...简言之
您可以通过声明
来取消支持变量/// <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和/或set上执行其他逻辑。
例如,您希望创建一个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的命名指南
答案 2 :(得分:0)
创建属性的正确方法实际上取决于您要完成的任务。如果您只想创建一个属性以供进一步使用,您可以创建速记方式:
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是原始类型。
答案 3 :(得分:0)
这里是您问题的快速摘要。
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
字段/属性是可访问类型的。所以要隐藏它们,你只需要制作它们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#?
答案 4 :(得分:0)
Unity引擎上下文中的属性模式往往与C#的“规范”略有不同,因为您通常对在编辑器中创建可调整数据感兴趣。这意味着序列化。
有关更深入的讨论,请参阅:https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
以下模式很常见,后台字段可由开发人员设置,无需重新编译,并且在运行时无法通过外部代码进行更改。
[SerializeField]
private int editableInEditor;
public int NotEditableInEditor
{
get { return editableInEditor; }
}
这种模式也是如此,一个懒惰的人。
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;
}
}