2015-12-21 104 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