什么是申报财产的最佳方式

时间:2015-01-30 01:51:15

标签: c# unity3d

我从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中。

5 个答案:

答案 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

...简言之

  • public =可从任何地方访问,不要将属性的支持变量声明为公共,否则人们可以简单地跳过您的属性访问者。
  • protected =在您的班级和继承班级的班级
  • 中可访问
  • internal =在同一个程序集中可访问
  • protected internal =可在同一个程序集中访问,也可以从 继承该类的类
  • private =仅在您的班级内访问

您可以通过声明

来取消支持变量
/// <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#的“规范”略有不同,因为您通常对在编辑器中创建可调整数据感兴趣。这意味着序列化。

  • Unity无法序列化属性
  • Unity可以序列化从UnityEngine继承的基本类型和类型的字段。对象是序列化引用
  • Unity也可以序列化上述类型的列表和数组
  • MonoBehaviours上的序列化字段在编辑器中公开,可编辑
  • 公共字段默认为序列化,如果使用[SerializeField]属性标记,则为私有字段。
  • 如果类是MonoBehavior上的字段,Unity也会序列化标有[System.Serializable]的类的字段

有关更深入的讨论,请参阅: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;
     }
}