首页 > 解决方案 > C#:泛型类中的受保护变量可以由该泛型类的不同子类访问。我可以防止这种情况吗?

问题描述

假设我有一个泛型类 Foo,它有一个受保护的变量

public class Foo<T> 
{ 
    protected bool knowsFu; 
}

我还有 2 个子类:Bar 和 Pipe

public class Bar : Foo<Bar> {}

public class Pipe : Foo<Pipe> {}

实际上,我可以在 Pipe FROM Bar 中访问 knowFu,例如:

public class Bar : Foo<Bar> 
{
    void UpdateFuInOtherClass(Pipe p)
    {
        p.knowsFu = false;
    }
}

这是预期的行为吗?(如果是这样,用例会是什么?)

我有没有办法阻止其他 Foo 子类修改/访问我当前子类中的受保护变量?

更具体地说:我使用通用类来实现单例模式: https ://en.wikipedia.org/wiki/Singleton_pattern

但是,我目前可以访问任何单例的受保护实例变量,只要我在另一个单例中。有没有办法防止这种情况?

编辑:可能需要注意受保护的变量(knowsFu)实际上也是静态的。

EDIT2:好的,也许这个例子有点太笼统了..这就是我目前实际实现它的方式:

为什么使用单例?A:我在做的平台是Unity3D,在这个平台上使用的模式比较频繁

我有一个通用类型的抽象类 SingletonBehaviour

public abstract class SingletonBehaviour<T> where T : MonoBehaviour
{
    public static T Instance { get { return instance; } }

    protected static T instance { get; private set; } }

    // Loading is done through Unitys Awake-Method
}

我正在使用的单例对象之一是 APIManager

public class APIManager : SingletonBehaviour<APIManager>
{
    // Methods like SendHTTPPost(), HTTPGet(), etc.
}

但是,由于我的大多数项目都需要比这更好的 API 实现,所以我目前正在做的是:

public class ProjectAAPIManager : APIManager 
{
    // Overriding Instance so my return value is not APIManager but instead ProjectAAPIManager
    public static new ProjectAAPIMamager Instance { get { return (ProjectAAPIManager)instance; } }
}

这 ^ 是我的(内部)实例变量受到保护而不是私有的原因。

但是,正因为如此,我项目中的任何其他 SingletonBehaviour 现在都可以访问我的 ProjectAAPIManager 上的(内部)实例变量

public class GameController : SingletonBehaviour<GameController> 
{
    private void AMethod()
    {
         // Accessing inner variable instead of public one
         ProjectAAPIManager.instance.DoSomething();
    }
}

由于它只是吸气剂,因此目前这并不重要。但是,如果我也需要访问我的子类中的设置器怎么办?

另外:通用输入我的 APIManager 是否值得?

标签: c#genericssingletongeneric-programming

解决方案


您不应该有实现通用单例类的类。否则,默认情况下,子类可以访问您的受保护字段(这就是“受保护”关键字的作用)

相反,您应该这样做:

class Program
{
    static void Main(string[] args)
    {
        var barInstance = Foo<Bar>.GetInstance();
    }
}

public class Foo<T> where T : new()
{
    protected bool knowsFu;

    private static T _instance;

    public static T GetInstance()
    {
        if (_instance == null)
            _instance = new T();

        return _instance;
    }
}

public class Bar
{
    public Bar()
    {
    }
}

编辑1:

要使用单例,您不应该让另一个类实现单例行为(这不是单例模式的工作方式)。要使用与第二个示例相同的类,您应该这样做。

public class SingletonBehaviour<T> where T : new()
{    
    public static T Instance 
    { 
        get 
        {
            if(instance == null)
                instance = new T()
            return instance; 
        } 
    } 
    private static T instance { get; set; } 
}

public class APIManager // This class should not inherit from the SingletonBehavior class
{
    // Methods like SendHTTPPost(), HTTPGet(), etc.
}

public class ProjectAAPIManager : APIManager 
{
    public ProjectAAPIManager GetInstance() => SingletonBehavior<ProjectAAPIManager>.Instance();
}

推荐阅读