2012-03-05 58 views
5

我試圖理解爲什麼這個轉換不起作用:爲什麼這個C#代碼示例沒有工作?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace CastTest { 

    class Foo {} 

    // I want to use this kind of like a typedef, to avoid writing List<Foo> everywhere. 
    class FooList : List<Foo> {} 

    class Program { 
     static void Main(string[] args) { 
      FooList list = (FooList) Program.GetFooList(); 
     } 

     // Suppose this is some library method, and i don't have control over the return type 
     static List<Foo> GetFooList() { 
      return new List<Foo>(); 
     } 
    } 
} 

這會產生一個運行時錯誤:

InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List`1[CastTest.Foo]' to type 'CastTest.FooList'.

任何人都可以解釋爲什麼這不工作,以及是否我可以以某種方式解決這個問題?

+0

哪一行產生錯誤? – ChrisF 2012-03-05 22:26:52

+0

這是正確的說:FooList是列表,或列表是FooList? – 2012-03-05 22:29:43

+0

@AnthonyPegram前者。 – hvd 2012-03-05 22:31:33

回答

5

您無法自動從父類轉換爲派生類:只是因爲你正在試圖投的對象是List<Foo>並不一定使之成爲FooList

退房:

http://social.msdn.microsoft.com/Forums/is/csharplanguage/thread/f7362ba9-48cd-49eb-9c65-d91355a3daee

你可以寫一個List<Foo>轉換爲FooList操作,可能使用AddRange填充值,如:

class FooList 
{ 
public explicit operator FooList(List<Foo> arg) 
{ 
    FooList result = new FooList(); 
    result.AddRange(arg); 
    return result; 
    } 
} 

此外,最好只使用一個using別名http://msdn.microsoft.com/en-us/library/sf0df423(v=vs.80).aspx

using FooList = List<Foo>; 

這樣你實際上並沒有繞過不必要的派生類。

+1

也許低調? – user1096188 2012-03-05 22:27:27

+0

謝謝,使用'using'是一個很好的提示......我唯一的問題(以及我試圖用類來解決它的原因)是'using'不能依賴於另一個' using'。與'using'需要使用完全限定的類型名稱(即,您需要使用'System.Collections.Generic.List'而不是'List')和'using'聲明相結合才能真正快速地實現真正的羅嗦。 – Eric 2012-03-05 22:45:11

7

只因爲你的FooList是一個List不會使List成爲FooList。

4

這種方法:

static List<Foo> GetFooList() { 
    return new List<Foo>(); 
} 

...不返回FooList。你的代碼實際上是這樣的:

FooList list = (FooList) new List<Foo>(); 

這根本不起作用。這是無效的:

string x = (string) new object(); 

你不會期望工作,你會嗎?那麼爲什麼你的FooList版本工作?

2

最接近C#有一個typedef被稱爲使用別名指令:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace CastTest { 
    using FooList = List<Foo>; 

    class Foo {} 

    class Program { 
     static void Main(string[] args) { 
      FooList list = Program.GetFooList(); 
     } 

     // Suppose this is some library method, and i don't have control over the return type 
     static List<Foo> GetFooList() { 
      return new List<Foo>(); 
     } 
    } 
} 

你有什麼創造了一個派生類FooList,但是這創造了一個別名FooList。它與List<Foo>沒有多少兼容,它List<Foo>

1

既然你知道一個FooList實際上是List<Foo>的另一個名字,它可能看起來很奇怪。但考慮到FooList本身可能包含成員,編譯器不應該允許演員表演變得明顯。想象一下你以後在FooList上引入方法(Bar())。 List<Foo>上不存在此方法,如果允許賦值(或強制轉換),則類型系統會簡單地中斷。

2

因爲不是所有的單子都是FooList。例如,我可以有:

public class AnotherFooList : List<Foo> 
{ 
    public object AdditionalPropery {get; set; } 
} 

它也從列表中繼承,但不一樣的FooList和FooList是不一樣的,因爲它。

1

你不能向上轉型;但是您可以創建FooList的新實例及其內容

class Foo { } 

    // I want to use this kind of like a typedef, to avoid writing List<Foo> everywhere. 
    class FooList : List<Foo> {} 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      FooList l = new FooList(); 
      l.AddRange(GetFooList().Select(foo => foo)); 

      Console.ReadLine(); 
     } 

     // Suppose this is some library method, and i don't have control over the return type 
     static List<Foo> GetFooList() 
     { 
      return new List<Foo>(); 
     } 
    } 
相關問題