在不更改父类的情况下更改子类中的静态变量

本文关键字:静态 变量 子类 情况下 父类 | 更新日期: 2023-09-27 18:27:46

我希望a.ID()返回0,b.ID()则返回1,这是我的代码:

public class A {
public static int id;
public int ID() {return id;}
}
public class B : A { }
public class Main {
    void Program() { //This executes when I execute the program
        A.id = 0;
        B.id = 1;
    }
}

但它不起作用,这也不起作用:

public class A {
    public static int id;
    public int ID() {return id;}
}
public class B : A {
    public new static int id; //id is actually 1 but ID() is still 0
}
public class Main {
    void Program() { //This executes when I execute the program
        A.id = 0;
        B.id = 1;
    }
}

我该怎么解决这个问题?

在不更改父类的情况下更改子类中的静态变量

您可以创建两个静态变量和一个虚拟属性

    public class A
    {
        private static int _idA;

        public virtual int Id
        {
            get { return _idA; }
            set { _idA = value; }
        }
    }
    public class B : A
    {
        private static int _idB;
        public override int Id
        {
            get { return _idB; }
            set { _idB = value; }
        }
    }

或者一个属性并使用新的关键字覆盖它

    public class A
    {
        public static  int Id { get; set; }
    }
    public class B : A
    {
        public static new int Id { get; set; }
    }

要测试第一个解决方案,您可以尝试以下

static void Main(string[] args)
{
    A test = new B();
    new B().Id = 3;
    new A().Id = 2;
    test.Id = 1;
    Console.WriteLine(test.Id + " " + new B().Id + " " + new A().Id);
    Console.ReadKey();
}

如果您可以接受这些规则:

  • 数字可以是任何数字,即任何合法的int
    • 它们不必从0开始
    • 它们不必为每种新的独特类型增加1
  • 允许在执行程序之间更改数字
    • 即。运行程序后,类型A返回id 33554436
    • 您更改程序(在其他地方)并重新运行,现在类型A返回id 33554437(不同的值)

那么这里有一种获取您的身份证的方法:

public class Base
{
    public int ID
    {
        get
        {
            return GetType().MetadataToken;
        }
    }
}

你不需要重写这个属性来获得每个类型的唯一id,但你不能再保证值是什么,下面是两个这样的派生类的输出示例:

33554436
33554437

如果我在这两个和reran之间添加一个新类型,我得到:

33554436
33554438

如果你担心持续的反思之旅会很昂贵,这里有一个替代声明:

public class Base
{
    private readonly Lazy<int> _ID;
    protected Base()
    {
        _ID = new Lazy<int>(() => GetType().MetadataToken);
    }
    public int ID
    {
        get
        {
            return _ID.Value;
        }
    }
}

您可以将ID方法设为虚拟方法,并在B类中覆盖它,如下所示:

public class A
{
    public static int id;
    public virtual int ID() { return id; }
}
public class B : A
{
    public static int id;
    public override int ID()
    {
        return id;
    }
}

这里有另一种使用反射的方法:

public class A
{
    public static int id;
    public int ID()
    {
        return (int)this.GetType()
            .GetField("id", BindingFlags.Static | BindingFlags.Public)
            .GetValue(null);
    }
}
public class B : A
{
    public static int id;
}

这样,您就不必在每个子类上重写ID方法。但是,您仍然需要在每个子类中定义一个静态id字段。