为啥我的函数不能访问它所在类的私有变量 INSIDE?

Posted

技术标签:

【中文标题】为啥我的函数不能访问它所在类的私有变量 INSIDE?【英文标题】:Why can't my function access a private variable INSIDE of the class it's in?为什么我的函数不能访问它所在类的私有变量 INSIDE? 【发布时间】:2020-08-01 08:58:14 【问题描述】:

编辑:我对空错误表示什么并不感到困惑,我知道我的列表为空。我只是不确定为什么在这种情况下它会为 null,或者为什么将我的列表设置为 public 突然解决了这个问题。

所以,我正在尝试创建一个函数,如果它满足条件,它将将对象添加到列表中。该函数接受它正在检查的标签,以及如果可能的话它将添加到的特定列表。我这样做的原因是因为我有两个列表,我宁愿两个列表都只需要一个函数。

这一切都很好,但我遇到了一个问题,它不...真的似乎工作,除非列表设置为公开?如果我能帮上忙,我宁愿不这样做。 我不明白为什么,因为它可以很好地处理私有 gameObject 引用,并且在同一个位置声明,并且该函数在同一个类中,但是在列表为私有时尝试调用此函数只会给我一个 null对象引用错误,在这种情况下,我已将其范围缩小到为 null 的列表,而不是对象?

这没什么大不了的,因为我可以改变一些事情来避免公开列表,但我真的很困惑为什么会发生这种情况?我试过明确地通过 ref 传递,但这给出了同样的问题。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickHandler : MonoBehaviour

    GameObject clickedMob = null;

    List<GameObject> selectedMinions;
    List<GameObject> selectedHostiles;

    void Update ( )
    

        if ( Input.GetButtonDown("Click"))
        
            switch (clickState)
            
                case NextClickAction.Nothing:
                     
                    break;

                case NextClickAction.TargetFriendly:
                    

                       hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

                        if ( hit )
                        
                            if ( hit.transform != null )
                            
                                clickedMob = hit.transform.gameObject;
                                CheckObject("Minion", selectedMinions);
                            
                        
                    
                    break;

                case NextClickAction.TargetHostile:
                    
                        hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

                        if ( hit )
                        
                            if ( hit.transform != null )
                            
                                clickedMob = hit.transform.gameObject;
                                CheckObject("Hostile", selectedHostiles);
                            
                        
                    
                    break;

                default:
                    
                        Debug.Log("why do you have an enum this big");
                        DeactivateClick();
                        Debug.LogError("Enum set outside of index. Returned to 0.");
                        break;
                    
            

        
       //  end of update

    private void CheckObject ( string tag , List<GameObject> mobList)
    
        if ( clickedMob.CompareTag(tag) )
        
            if ( clickedMob.GetComponent<Animator>() != null )
            
                ClickedMobAnimator = clickedMob.GetComponent<Animator>();

                switch (ClickedMobAnimator.GetBool("Selected"))
                
                    case true:
                        ClickedMobAnimator.SetBool("Selected", false); // Setting the object to have a little box around it when it's selected.

                        mobList.Remove(clickedMob);
                        Debug.Log(mobList.Count + " " + clickedMob);
                        break;

                    case false:
                        ClickedMobAnimator.SetBool("Selected", true);
                        mobList.Add(clickedMob); 
                        Debug.Log(mobList.Count + " " + clickedMob);
                        break;
                
            

        
    

这段代码的输出:

NullReferenceException: Object reference not set to an instance of an object
ClickHandler.CheckObject (System.String tag, System.Collections.Generic.List'[T] mobList) (at Assets/Scripts/ClickHandler.cs:119)

而且我知道在这种情况下对象不是 null,因为我有一个调试日志打印该对象。它就在那里。

【问题讨论】:

您需要实际创建一个new List - 否则默认值保持null。 (Unity会自动为public编辑器的成员变量创建) 这能回答你的问题吗? What is a NullReferenceException, and how do I fix it? @devNull 不完全是。要么,要么我看的不太对。我的问题不是它为空,而是更具体地说,为什么当列表为私有时它才为空。据我所知,这应该没什么区别,因为所有东西都在同一个类中,对吧? @UnholySheep 首先,你好,羊同胞! :P 我不完全确定你的意思是什么?比如,在函数中创建一个临时列表,然后返回它,还是别的什么? @UnholySheep OH MY GOSH,我完全忘记了这一步!我知道这很简单,非常感谢!现在已经修好了。 ^^ 【参考方案1】:

由于您的列表是非公开且非序列化的字段,因此您无法从检查器分配它们以自动创建新的列表实例,因此在 ClickHandler 脚本中添加 Awake 方法,将它们实例化为新的列表对象。

void Awake() 
    selectedMinions = new List<GameObject>();
    selectedHostiles = new List<GameObject>();

或者你可以在声明时做同样的事情

List<GameObject> selectedMinions = new List<GameObject>();
List<GameObject> selectedHostiles = new List<GameObject>();

【讨论】:

我决定选择后者,它对我有用。我有点不好意思忘记了这一步,但很高兴这次我不必花一个下午来自己解决这个问题。谢谢。

以上是关于为啥我的函数不能访问它所在类的私有变量 INSIDE?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个朋友功能不能访问类的私有成员?

为啥我可以在复制构造函数中访问私有变量?

为啥嵌套的子类可以访问其父类的私有成员,而孙子却不能?

内部类

复习 类的属性总结 类的方法总结

让公共成员变量访问 C++ 中同一类的私有成员