2015-12-21 99 views
4

我想这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; 
    } 
} 

我该如何解决这个问题?

+0

为什么你需要这个?为什么你需要它是静态的? –

+0

将你的'static int'变成'properties'。 –

+0

[new modifier](https://msdn.microsoft.com/en-us/library/435f1dw2.aspx)只是隐藏一个成员。你需要重写它,但它是静态的,所以你不能。无论如何,你为什么要为它有一个静态ID和一个实例getter? –

回答

2

您可以创建两个静态变量和一个虚拟财产

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; } 
     } 
    } 

或者一个属性,并使用new关键字来覆盖它

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(); 
} 
+0

我是否仍然可以通过test.Id访问它:a test = new b();?它会返回b的ID吗? – Yoshi

+0

@Yoshi是的,它会 – Valentin

1

您可以使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; 
    } 
} 

这里是另一种方式来做到这一点,使用Reflection

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字段。

+0

我也想到了这一点,但a和b是例子,这将意味着我需要在我的每个类的代码 – Yoshi

+0

@Yoshi,看到更新的另一个解决方案 –

+0

有多快反射? (或者比其他方法慢多少倍) – Yoshi

1

如果你能接受这些规则:

  • 的数字可以是任何东西,即。任何法律int
    • 他们不必从0开始
    • 他们不必为每个新的独特的类型
  • 上浮了1号被允许的执行之间更改程序
    • ie。您运行您的程序和A型收益ID 33554436
    • 您更改程序(其他地方),然后重新运行,现在A型收益ID 33554437(不同的值)

然后在这里是一种方法,让您的ID:

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

你并不需要重写这个属性来获得唯一的ID对每个类型的,但你不能保证值将是什么,这里有两个这样的派生类输出例如:

33554436 
33554437 

如果我加入这两个和重新运行之间的新的类型,我:

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; 
     } 
    } 
} 
+0

现在我在另一个类中制作了一本字典。 – Yoshi