这可能是一个非常基本的问题,但我希望得到一些澄清,之所以发布这篇帖子,是因为最近我被反复告知,并在其他帖子中看到,在声明变量时永远不要使用public,所以我有点困惑.这也包括[SerializeField].我尽可能地try 使用private来声明变量,但是当我需要引用另一个脚本中的变量时,我需要将变量从private更改为public,否则我会得到"由于保护级别的原因,变量无法访问".这是可以接受的吗?还是有办法绕过这一点?

因为目前我的一个大脚本中有大约30个变量,其中25个变量都是public.

// ScriptA
public bool testBool;
private bool testBool;
[SerializeField] private bool testBool;

如果我要在另一个脚本中引用这三个布尔中的一个(例如ScriptB),则只有public bool testBool可以工作,如果我使用floatVector3等等而不是bool,情况也是如此.

当使用类似[SerializeField] private bool testBool;的值时,当try 在不同的脚本中使用该bool时,也会出现相同的"不可访问"错误,所以我只是好奇我是应该做什么,还是应该放弃它,继续我的方法.

推荐答案

通常,您希望使所有内容尽可能少地可访问(Encapsulation)!

所以事情应该是这样的

  • 尽可能为private(因此,这也是类型成员的默认/隐式可访问性)
  • 在继承的情况下需要protected美元
  • internal-意味着只能访问同一程序集中的所有内容(也是类型的默认可访问性--人们最常使用public是一个坏习惯,我自己也是如此;)
  • 如果它确实提供了一些全局API并且在程序集外部是必需的,则返回public

(对于一些非常特殊和尖端的情况-例如测试-您也可以通过[InternalsVisibleTo]expose 某些装配桥)

(也有其他情况下,你会坚持拥有更多的public一样的东西,例如,当涉及到修改时-请参阅下面的 comments )


通常,在c#中,对任何公共内容使用properties也是一种常见的做法(例如,参见Is it bad practice to use public fields?).

简而言之:它们基本上是getter/setter方法.它们可以是backing field and implement additional logic,也可以是auto-properties,如下例所示.此外,您还可以控制set(Ter)部分的可访问性(理论上,您can也可以控制get部分的可访问性,但set的可访问性高于get是很不寻常的)

Unity甚至没有文档支持auto-properties在Inspector中使用

[field: SerializeField] public bool SomeBool { get; private set; }

...所以,公共fields不是向其他脚本提供值的only种方式.


有很多很多的方法-所以基本上可以归结为偏好和您的用例.

总的来说,我会 Select

// This is only used by this type
private bool someBool; 

如果这需要由用户调整-也就是判断员

// This is only used by this type
[SerializeField] private bool someBool; 

如果另一个脚本要求为read,您可以 Select

// That's the backing field approach
public bool SomeBool => someBool;

// equals
public bool SomeBool
{
    get => someBool;
}
// equals
public bool SomeBool
{
    get
    {
        return someBool;
    }
}

或者如上所述,使用序列化的自动属性

[field: SerializeField] public bool SomeBool { get; private/*or protected*/set };

并且只有当其他脚本也是setthis时,您才可以使用

// For simplicity and less typing effort
// I also use this for fast prototyping and quickly expose things in the Inspector
// but this shouldn't stay the long-term code
public bool SomeBool;

对于运行时的东西,您只需坚持

// Can have a default value and behaves similar to a public field
public bool SomeBool { get; set; }

但如果需要,您也可以在判断器中显示它

[field: SerializeField] public bool SomeBool { get; set; }

自动属性可以像字段一样,也可以直接用值初始化.


Sidenote:序列化的属性带有一些关于定制Editor实现的问题--您必须通过虚拟支持字段serializedObject.FindProperty($"<{propertyName}>k__BackingField")

Csharp相关问答推荐

当我 for each 请求创建实例时,我是否应该在C#中部署httpClient?

如果没有中间变量,可空引用类型将无法工作

需要深入了解NpgSQL DateTimeOffset处理

在. net毛伊岛窗口的深度链接已经创建""

C#.NET依赖项注入顺序澄清

应用程序启动器,可 Select 物理屏幕

.NET 6控制台应用程序,RabbitMQ消费不工作时,它的程序文件中的S

在静态模式下实例化配置

在ASP.NET Core Web API项目中通过中间件修改`Request.Path`不会更改使用的控制器/操作

单行上的ReSharper数据标注

在swagger示例中添加默认数组列表

自定义列表按字符串的部分排序

将内置的OrderedEumable&Quot;类设置为内部类有什么好处?

如果是,我怎么才能让这个加75,如果不是,我怎么才能减go 100?

将操作从编辑页重定向到带参数的索引页

如何在GRPC代码First服务的返回类型上使用多态性?

在C#ASP.NET内核中使用INT AS-1进行控制器场景的单元测试

在';、';附近有错误的语法.必须声明标量变量";@Checkin";.';

是否可以在Entity Framework Core中使用只读 struct 作为拥有实体?

当`JToken?`为空时?