简体   繁体   English

如果 Unity C# 中的语句为 false,但 Watch 中的语句为 true

[英]If statement in Unity C# false, but true in Watch

I am currently developing an user interface editor for Unity3D.我目前正在为 Unity3D 开发一个用户界面编辑器。 At this point I have a dictionary, with a key and value both representing a type.在这一点上,我有一个字典,其中的键和值都代表一种类型。 Based on the key type I want to add a component of the value type to a gameObject and return it:基于键类型,我想将值类型的组件添加到游戏对象并返回它:

protected Dictionary<string, string> eventHandlers = new Dictionary<string, string>();

public virtual EventHandler GetHandler(System.Type type)
{
    string name = type.Name;
    if(eventHandlers.ContainsKey(name))
    {
        System.Type eventHandlerType = TypeUtility.GetType(eventHandlers[name], null);
        return this.gameObject.AddComponent(eventHandlerType) as EventHandler;
    }
    return null;
}

The problem lies with my if statement.问题在于我的 if 语句。 Appearantly, eventHandlers.ContainsKey(name) returns false, because the return null statement is called.显然, eventHandlers.ContainsKey(name) 返回 false,因为调用了 return null 语句。 However, the dictionary does contain the key.但是,字典确实包含密钥。 Even weirder: if I enter this statement into my watches in Visual Studio, it is true.更奇怪的是:如果我在 Visual Studio 中将这个语句输入到我的手表中,它是真的。

  • I started out with a Dictionary but that wouldn't work out either.我从字典开始,但这也行不通。
  • I looked into type, and it gave an exception for type.DeclaringMethod: System.InvalidOperationException: DeclaringMethod can only be used on generic arguments.我查看了类型,它为 type.DeclaringMethod: System.InvalidOperationException: DeclaringMethod can only be used on generic arguments 提供了一个异常。 However, I can access name fine, as you can see in the code above.但是,我可以正常访问 name,正如您在上面的代码中看到的那样。 String name is the right value and it doesn't break here.字符串名称是正确的值,这里不会中断。

Does anybody know why my if statement is false, when it is true in the watch?有人知道为什么我的 if 语句是假的,而在手表中是真的吗? Can anybody point me in the right direction?有人能指出我正确的方向吗?

[edit] The values are: [编辑] 值是:

name    "IOnClick"  System.String

eventHandlers   
    Count=1 
    System.Collections.Generic.Dictionary`2
        [
            [System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],
            [System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]
        ]
    ["IOnClick"]    "OnClickHandler"    System.Collections.DictionaryEntry

type    "InterfaceEditor.EventSlots.IOnClick"   System.Type
    DeclaringMethod System.InvalidOperationException: DeclaringMethod can only be used on generic arguments System.Reflection.MethodBase
    Name    "IOnClick"  System.String

[edit2] So, I figured out where my problem lies. [edit2] 所以,我找到了我的问题所在。

The code above resides in my class InterfaceElement:上面的代码驻留在我的类 InterfaceElement 中:

public abstract class InterfaceElement : MonoBehaviour, ISerializationCallbackReceiver
{
    protected Dictionary<string, string> eventHandlers = new Dictionary<string, string>();
}

For my different InterfaceElements, like my button, I figured I could just override the dictionary like this:对于我不同的 InterfaceElements,比如我的按钮,我想我可以像这样覆盖字典:

public class Button : InterfaceElement, IOnClick
{
    protected new Dictionary<string, string> eventHandlers = new Dictionary<string, string>()
    {
        { typeof(IOnClick).Name, typeof(OnClickHandler).Name }
    };
}

Appearantly, C# or Unity doesn't like this.显然,C# 或 Unity 不喜欢这样。 What's the correct way to do something simular?做一些类似的事情的正确方法是什么? I can't use the constructor, cause my InterfaceElement is a MonoBehaviour, right?我不能使用构造函数,因为我的 InterfaceElement 是 MonoBehaviour,对吗?

So.所以。 It turns out new does not do what I thought it would.事实证明, new 并没有像我想象的那样做。 New does not override a field, but rather hides the base field. New 不会覆盖字段,而是隐藏基本字段。 This means the base class will still see the base field.这意味着基类仍然会看到基字段。 My solution is to not use a field, but a method to return the dictionary, like this:我的解决方案是不使用字段,而是使用返回字典的方法,如下所示:

public abstract class InterfaceElement : MonoBehaviour
{
    protected virtual Dictionary<System.Type, System.Type> GetEventHandlers()
    {
        return null;
    }

    public virtual EventHandler GetHandler(System.Type type)
    {
        Dictionary<System.Type, System.Type> eventHandlers = GetEventHandlers();
        if(eventHandlers != null && eventHandlers.ContainsKey(type))
            return this.gameObject.AddComponent(eventHandlers[type]) as EventHandler;
        return null;
    }
}

public class Button : InterfaceElement, IOnClick
{
    protected override Dictionary<System.Type, System.Type> GetEventHandlers()
    {
        return new Dictionary<System.Type, System.Type>()
        {
            {typeof(IOnClick), typeof(OnClickHandler)}
        };
    }
}

Thank you for commenting and helping to find an answer!感谢您发表评论并帮助找到答案!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM