簡體   English   中英

C#中的靜態類列表

[英]List of static classes in C#

我想要一些類,它們都擴展了一個基本抽象類。

然后,我希望有一個對象,每個對象存儲這些類的一個子集,並調用它們實現的方法。

所以我想-我對存儲的對象不執行任何操作,所以我們只需將這些類設置為靜態,就不會浪費存儲對象的內存,而只是對靜態類的引用,因此可以調用靜態函數。 問題是-我該怎么做?

對於那些喜歡代碼的人,這是我需要的:

public static abstract class A {
    public static abstract void F();
}

public static class B : A {
    public static override void F() {
        ...
    }
}
// Class Storage of course does NOT work, its just here to illustrate what I need
public class Storage {
    private List<A> list;
    public void AddElement(A element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(A element in list)
            element::F();
    }
}

有什么辦法可以做這樣的事情嗎? 或針對此問題的另一種解決方案?

不,你不能那樣做。 您嘗試執行的操作存在許多問題:

  1. 您不能將靜態類型用作類型參數,例如List<A>
  2. 您不能將靜態類型用作方法參數,例如AddElement(A element)
  3. 您無法將靜態類型抽象化,因為無法從其繼承。
  4. 您不能將靜態方法抽象化,即使在非靜態類中也是如此,因為它不能被覆蓋。

從您對問題的描述方式來看,我看不到這里需要靜態類型或靜態方法。 只需創建一個簡單的抽象類並從中繼承即可:

public abstract class A {
    public abstract void F();
}


public class B : A {
    public override void F() {
        ...
    }
}

public class Storage {
    private List<A> list;
    public void AddElement(A element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(A element in list)
            element.F();
    }
}

另外,您可以創建一個List<Type>並使用反射對那些類型調用靜態方法。 例如:

public static class A {
    public static void F() { ... }
}
public static class B {
    public static void F() { ... }
}

List<Type> typeList = new List<Type> { typeof(A), typeof(B) };
foreach(var type in typeList)
{
    type.GetMethod("F").Invoke(null, null); 
}

但是使用反射比使用直接方法調用要慢,並且您將使用此方法失去所有類型安全性(除非您自己編寫類型檢查)。

pswg的答案顯示了處理您提供給我們的代碼的正確方法,但是聽起來您想做的就是調用方法列表。 這些方法沒有關聯的數據,因此您考慮將它們設為靜態類。 為什么不使用Action?

public class Storage {
    private Action list;
    public void AddElement(Action element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(Action element in list)
            element();
    }
}

然后,您可以像這樣將方法添加到存儲中:

public void DefineStoredFunctions(Storage s)
{
    s.AddElement(() => { first function F });
    s.AddElement(() => { another function F });
    s.AddElement(() => A.F()); //or just call function defined on A
    s.AddElement(B.F); //or get rid of lambda altogether
    //and so on...
}

編輯:如果這不是您要的內容,則應采用其他答案的方法並使用普通對象

這個想法有很多錯誤:

  • 靜態類只有一個實例,只能在“靜態上下文”中訪問。 您無法定義靜態類,然后將其添加為列表的元素。

  • 靜態類不能從Object繼承,也不能從Object繼承(隱式執行)。

  • 由於繼承不適用於靜態變量,因此虛擬或抽象重寫方法的概念也不適用於靜態變量。

  • 靜態代碼只使用稍微少一點的內存,就象普通對象那樣使用任何靜態實例狀態(字段,屬性)。

只需使用普通對象即可。 “過早的優化是計算機編程中所有邪惡的根源-無論如何,絕大部分。” 我沒有比我正在回答的問題更好地說明該陳述的真實性,在該問題中,非常少的內存節省用於證明試圖打破面向對象設計的基本規則(即, 最大限度地減少靜態使用) 。

如果要獲取對象的實例,請確保您擁有的實例與其他人的實例相同(換句話說,只允許存在一個實例),但仍將其視為對象的實例,請看一下在單例模式 C#中的Singleton可以從其他類繼承並可以從其他類繼承,可用的實例正是該實例,因此您可以將其傳遞給其他代碼,這些代碼不必關心它的來源(例如列表),但是您仍然可以使用靜態訪問器從不介意的任何地方獲取該實例,並且可以強制您只有一個實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM