2015-09-08 54 views
0

我有CollectionBase這樣子類:蒙上了CollectionBase的子類的泛型列表沒有指定類型明確

public abstract class BaseList : CollectionBase 
{ 
    public abstract Type ListType { get; } 
} 

public class MyClassList : BaseList 
{ 
    public override Type ListType 
    { 
     get { return typeof(MyClass); } 
    } 
} 

所以我知道的類型在編譯時。我想添加一個方法ToGenericList()到 我的BaseList類,它會將任何BaseList轉換爲類型 ListType的通用List

這不起作用:「類型參數不能從使用推斷」

public List<T> ToGeneric<T>() 
{ 
    return List.Cast<T>().ToList(); 
} 

因爲很顯然,我可以 只是這樣做:

someList.Cast<MyClass>().ToList(); 

或本:

someList.ToGeneric<MyClass>(); 

但這變得非常繁瑣當我與有列表和我的名單 列表對象工作想要在它們上面使用一堆LINQ方法,並且類名長度超過30個字符。

是否有任何解決方案不涉及調用者指定類型或調用 ?

+1

有沒有你不把一個通用的'BaseList '首先具體原因是什麼? –

+0

@LucasTrzesniewski是的。我沒有設計這個系統,那個不再爲這個公司工作的人,同事們在編寫新的代碼以保持一致性時,模仿以前的設計。這個舊的,複雜的系統現在有數千行使用這些自定義非通用列表。然而,我的同事和我仍然經常用'.Cast <>()來使用泛型。但是,正如我所說,這很麻煩。 – nanny

+0

你可以在每個子類中定義一個單獨的'ToList()',指定正確的類型有:'公開名單 ToGeneric()',例如..我不認爲有辦法讓一個BaseClass的方法,這項工作。 – Blorgbeard

回答

2

沒有辦法讓編譯器通過返回類型來推斷。一種選擇是將方法添加到每個集合類型返回一個泛型集合:

public class MyClassList : BaseList 
{ 
    public override Type ListType 
    { 
     get { return typeof(MyClass); } 
    } 
    public List<MyClass> ToGeneric() 
    { 
     return this.Cast<MyClass>.ToList(); 
    } 
} 

注意,因爲唯一改變的事情就是返回類型有沒有把這個基類的方式(你不能通過僅更改返回類型來重載方法)。

如果你不能/不想改變基本類型,您可以使他們擴展方法,但你仍然必須爲每個類型的方法。

+0

是的,我想到了這一點,但是我們有超過400個來自'BaseList'的子類,我認爲這是不切實際的。哦,謝謝。 – nanny

+0

你確定沒有可能的方法來從基類做到這一點?如果是這樣,我不得不接受你的答案。 – nanny

1

如果您對列表有特定的命名約定,則可以嘗試使用大爆炸方法。

首先,聲明第二基類,引入中介機構層級:

public abstract class BaseList<T> : BaseList, IList<T> 
{ 
    public override Type ListType { get { return typeof(T); } } 

    // Delegate IList<T> implementation to the base class 

    public new IEnumerator<T> GetEnumerator() 
    { 
     return base.Cast<T>().GetEnumerator(); 
    } 

    public void Add(T item) 
    { 
     base.Add(item); 
    } 

    public bool Contains(T item) 
    { 
     return base.Contains(item); 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     base.CopyTo(array, arrayIndex); 
    } 

    public bool Remove(T item) 
    { 
     return base.Remove(item); 
    } 

    public int IndexOf(T item) 
    { 
     return base.IndexOf(item); 
    } 

    public void Insert(int index, T item) 
    { 
     base.Insert(index, item); 
    } 

    public new T this[int index] 
    { 
     get { return (T)base[index]; } 
     set { base[index] = value; } 
    } 
} 

然後,嗯......在執行你的代碼正則表達式替換。您可以使用VS 替換文件工具。

查找:

\bclass\s+(\w+)List\s*:\s*BaseList\b 

替換:

class $1List : BaseList<$1> 

這是否是可行取決於你的代碼,但它可能是一個開始。

一旦完成,您可以擺脫現在多餘的ListType覆蓋。