【问题标题】:How to, from static methods ; access a unique value of a static property used in a static method如何,从静态方法;访问静态方法中使用的静态属性的唯一值
【发布时间】:2015-12-22 16:32:04
【问题描述】:

我想在同一线程上运行的其他静态方法中访问静态字段的值。下面的代码中有一个例子:

这个脚本中的第一个类是ClassA。 ClassA 的工作是比较两个 Rect 值,如果两个比较的 Rect 值之间存在不等式,则将公共布尔值设置为 true;

在 classA 中,IsRectChanged 是一个 bool 方法,它接受 Rect 类型的参数对象并将其与 StoredRect 进行比较,Rect。当storedRectIsRectChangedRect 值不匹配时,该方法返回true。

    public class ClassA
    {
        private Rect storedRect;

        public ClassA() { }

        public bool IsRectChanged(Rect rect)
        {
            bool isChanged = !rect.Equals(storedRect);
            if(isChanged)
            {
                storedRect = rect;
            }

            return isChanged;
        }
    }

这是ClassB 我们在ClassB 中创建一个名为isRectChangedClassA 静态字段。 请勿更改 ClassB 中 MethodB 的结构。考虑静态和非静态类中的 50 种其他方法必须使用 ClassA 字段这一事实。需要更改ClassB 的结构以使代码正常工作会适得其反。

    public static class ClassB
    {
        private static ClassA RectHelper = new ClassA();

        public static void MethodB(Rect yourRect)
        {
           if(RectHelper.IsRectChanged(yourRect))
           {
               Debug.Log("Changes were made");
           }
        }
    }

ClassCClassDClassE在同一个线程上运行。它们都调用ClassB.MethodB并在MethodB的参数中分配一个new Rect

因为ClassC,ClassDClassE被调用ClassB.MethodB并在MethodB的参数中分配一个new Rect。它们各自覆盖静态字段ClassA RectHelperstoredRect 值。

因此,ClassA RectHelper.IsRectChanged 将永远为真。

如何解决这个问题而不必使ClassBClassAClassEMethodB 成为非静态的?**

    public class ClassC
    {
        public void UpdateEverFrame()
        {
            ClassB.MethodB(new Rect(0, 0, 20, 20));
        }
    }
    public class ClassD
    {
        public void UpdateEverFrame()
        {
            ClassB.MethodB(new Rect(100, 100, 10, 10));
        }
    }

这里在ClassE ClassB.MthodB 中被两个UpdateEverFrame 方法调用,其中一个接受一个int 参数。如果同时调用它们,它们会相互覆盖,因此系统会认为IsRectChanged 为真,并且始终返回真。这是个大问题。

我们不希望IsRectChanged 被覆盖,我们希望ClassB.MethodB 的每个调用都被视为不是静态的,因此IsRectChanged 永远不会被覆盖

    public class ClassE
    {
        public void UpdateEverFrame()
        {
            ClassB.MethodB(new Rect(0, 0, 20, 20));
        }

        public void UpdateEverFrame(int i)
        {
            ClassB.MethodB(new Rect(100, 100, 10, 10));
        }
    }

在我的问题中,当我说“访问静态属性的唯一值”时,我指的是ClassB.RectHelper

我知道 ClassB.RectHelper 是 STATIC,因此无论何时调用 MethodB,该值都将在 ClassCClassD 和 ClassE 类之间共享。但是我们能否解决这个问题,以便 ClassCClassD 不覆盖 ClassA 中的 storedRect 值?

【问题讨论】:

  • 请更好地描述您想要做什么。考虑提供一些代码来显示你得到的结果与你想要得到的结果形成对比。
  • 我更改了问题并添加了更多信息,请参阅 ClassE 和上面的描述
  • 对我们帮助您仍然没有帮助。你试过调试器吗?

标签: c# class methods static


【解决方案1】:

我没有达到目的,但您是否考虑过将ClassB 设为通用?类似的东西:

    public class ClassB<T>
    {
        private static ClassA if_rect_Changed = new ClassA();

        public static void MethodB(Rect yourRect)
        {
            if (if_rect_Changed.RectChanged(yourRect))
            {
                Debug.Log("Changes were made");
            }
        }

    }

并像这样使用它:ClassB&lt;ClassC&gt;.MethodB(rect),这样每个班级都将拥有“更改跟踪器”的“副本”,您将能够保持 MethodB 静态。

【讨论】:

    【解决方案2】:

    您为什么不跳过静态类 B 并在您的类 C 和 D 中创建类 A 的静态属性。您构建代码的方式对我来说似乎一团糟。我处理这个问题的另一种方法是做类似的事情:

    public class ClassA
    {
        protected Rect storedRect;
    
        public ClassA() { }
    
        public virtual void UpdateEverFrame();
    
        protected bool IsRectChanged(Rect rect)
        {
            bool isChanged = !rect.Equals(StoredRect);
            if(isChanged)
            {
                storedRect = rect;
            }
    
            return isChanged;
        }
    }
    
    public class ClassC : ClassA
    {
        public override void UpdateEverFrame()
        {
            if(IsRectChanged(new Rect(0, 0, 20, 20)))
            {
                 Debug.Log("Changes were made class C");
            }
        }
    }
    public class ClassD : ClassA
    {
        public override void UpdateEverFrame()
        {
            if(IsRectChanged(new Rect(100, 100, 10, 10)))
            {
                 Debug.Log("Changes were made class D");
            }
        }
    }
    

    【讨论】:

    • 如果 ClassD 使用 void Update 而不是 UpdateEverFrame 我需要向 ClassA 添加一个 vertual 方法,代码会变得过于粗糙。让我想使用的任何类 ClassA 继承 ClassA 会使一切变得不那么灵活
    • 您可以从 ClassA 中删除 UpdateEverFrame 函数并仅继承 storedRect 和 IsRectChanged 函数,然后在您的子类中实现您需要的任何功能。您的所有类都使用 storedRect 和 IsRectChanged,因此使用 ClassA 作为基类而不是每个其他对象都会覆盖的静态实例是合乎逻辑的。
    【解决方案3】:

    首先进行一些澄清。我假设您使用的是 System.Windows.Rect,对吗?更多说明...

    我们在 ClassB 中有一个 ClassA 的静态属性,名为 isRectChanged

    不,您在 ClassB 中有一个 ClassA 类型的静态字段,名为 RectHelperIsRectChanged 是 ClassA 的非静态方法。

    我们希望在同一线程上运行的其他静态方法中访问静态属性的值。

    由于它们在同一线程上,因此您不可能同时调用您的静态方法。到目前为止,没问题。

    它们都调用 ClassB.MethodB 并覆盖 MethodB 的 Rect 参数的值。两个类都使用ClassB.MethodB 的相同实例...

    它们不会覆盖 Rect 参数,而是各自提供一个Rect 对象。 ClassB 是实例,而不是 ClassB.MethodB

    ...永远是真的。

    不是这样,尝试运行下面的代码,你会看到只有第一个调用返回true

    ClassC c = new ClassC();
    c.UpdateEverFrame();
    c.UpdateEverFrame();
    c.UpdateEverFrame();
    

    但是如果你通过 ClassD 在行之间插入调用,是的,IsRectChanged 将返回 true 因为它是真的,Rect实际上是不同的。但是,这就是 static 的用途,即,它适用于 Singleton 类型的操作。

    如果您想要每个类 静态变量,则将静态变量放入每个类中。如果这需要您复制代码,请使用 模板。不必花哨,例如,只需将 ClassB 和对 ClassB 的方法的调用更改如下...

    public class ClassB<TClass> // the rest of the class is the same
    ...
    /* in ClassC */ ClassB<ClassC>.MethodB(new Rect(...));
    ...
    /* in ClassD */ ClassB<ClassD>.MethodB(new Rect(...));
    

    通过将ClassB制作成模板,每个ClassB都是一个不同的静态对象,每个都有自己的静态变量副本。现在,除了第一次调用 ClassCClassD 之外,以下代码将返回 false

            ClassC c = new ClassC();
            c.UpdateEverFrame();
            c.UpdateEverFrame();
            c.UpdateEverFrame();
            ClassD d = new ClassD();
            d.UpdateEverFrame();
            d.UpdateEverFrame();
            c.UpdateEverFrame();
            d.UpdateEverFrame();
    

    这是课程...

    public static class ClassB<TClass>
    {
        private static ClassA RectHelper = new ClassA();
    
        public static void MethodB(Rect yourRect)
        {
            if (RectHelper.IsRectChanged(yourRect))
            {
                Debug.WriteLine("Changes were made");
            }
        }
    }
    
    public class ClassC
    {
        public void UpdateEverFrame()
        {
            ClassB<ClassC>.MethodB(new Rect(0, 0, 20, 20));
        }
    }
    public class ClassD
    {
        public void UpdateEverFrame()
        {
            ClassB<ClassD>.MethodB(new Rect(100, 100, 10, 10));
        }
    }
    

    【讨论】:

    • 感谢您的回答。我更新了我的问题,使其更加具体和详细。我更正了我应该在哪里拥有财产的地方。除了更改 ClassBRectHelper 字段的结构方式之外,我无法更改 ClassB 的结构
    • 如果您可以将 ClassB 更改为模板,那会解决您的问题吗?当我阅读您的问题时,我仍然不确定我是否理解您的要求。
    • CassA's bool IsRectChanged() 当给定Rect 参数时,将检查Rect 参数是否等于storedRect,如果不是IsRectChanged 设置为true。让用户知道“哦,看看 rect 的值不匹配,有些地方改变了” 现在,我们不需要它是 Rect,它可以是 object。现在,ClassB 使用 ClassA 作为 RectHelper 。如果在任何时候 ClassB ,MethodB 的 Rect 参数 yourRect 不匹配 ClassA.storedRect 即 (RectHelper.storedRect) 这将被打印出来给用户 ("Changes were made");
    猜你喜欢
    • 2013-02-13
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2015-07-22
    • 2012-06-29
    相关资源
    最近更新 更多