2014-09-13 51 views
1

問題:我試圖強制轉換的對象類型回根類
我開始與通用雙向鏈表,我可以添加值,但無法檢索這些鑄字對象類C#

class CarPart 
{ 
    public long PartNumber; 
    public string PartName; 
    public double UnitPrice; 
} 

class DoublyLinkedList 
{ 
    private class DoublyLinkedListNode 
    { 
     private object element; 
     private DoublyLinkedListNode next; 
     private DoublyLinkedListNode previous; 

     public DoublyLinkedListNode(object element) 
     { 
      this.element = element; 
      this.next = null; 
      this.previous = null; 
     } 

     public DoublyLinkedListNode(object element, DoublyLinkedListNode prevNode) 
     { 
      this.element = element; 
      this.previous = prevNode; 
      prevNode.next = this; 
     } 

     public object Element 
     { 
      get { return this.element; } 
      set { this.element = value; } 
     } 

     public DoublyLinkedListNode Next 
     { 
      get { return this.next; } 
      set { this.next = value; } 
     } 

     public DoublyLinkedListNode Previous 
     { 
      get { return this.previous; } 
      set { this.previous = value; } 
     } 
    } 

    private DoublyLinkedListNode head; 
    private DoublyLinkedListNode tail; 
    private int count; 

    public DoublyLinkedList() 
    { 
     this.head = null; 
     this.tail = null; 
     this.count = 0; 
    } 

    public int Count 
    { 
     get { return this.count; } 
    } 

    public object this[int index] 
    { 
     get 
     { 
      if (index >= count || index < 0) 
      { 
       throw new ArgumentOutOfRangeException("Out of range!"); 
      } 
      DoublyLinkedListNode currentNode = this.head; 
      for (int i = 0; i < index; i++) 
      { 
       currentNode = currentNode.Next; 
      } 
      return currentNode.Element; 
     } 
     set 
     { 
      if (index >= count || index < 0) 
      { 
       throw new ArgumentOutOfRangeException("Out of range!"); 
      } 
      DoublyLinkedListNode currentNode = this.head; 
      for (int i = 0; i < index; i++) 
      { 
       currentNode = currentNode.Next; 
      } 
      currentNode.Element = value; 
     } 
    } 
    public void Add(object item) 
    { 
     if (this.head == null) 
     { 
      this.head = new DoublyLinkedListNode(item); 
      this.tail = this.head; 
     } 
     else 
     { 
      DoublyLinkedListNode newItem = new DoublyLinkedListNode(item, tail); 
      this.tail = newItem; 
     } 
     count++; 
    } 

    public void Insert(object item, int index) 
    { 
     count++; 
     if (index >= count || index < 0) 
     { 
      throw new ArgumentOutOfRangeException("Out of range!"); 
     } 
     DoublyLinkedListNode newItem = new DoublyLinkedListNode(item); 
     int currentIndex = 0; 
     DoublyLinkedListNode currentItem = this.head; 
     DoublyLinkedListNode prevItem = null; 
     while (currentIndex < index) 
     { 
      prevItem = currentItem; 
      currentItem = currentItem.Next; 
      currentIndex++; 
     } 
     if (index == 0) 
     { 
      newItem.Previous = this.head.Previous; 
      newItem.Next = this.head; 
      this.head.Previous = newItem; 
      this.head = newItem; 
     } 
     else if (index == count - 1) 
     { 
      newItem.Previous = this.tail; 
      this.tail.Next = newItem; 
      newItem = this.tail; 
     } 
     else 
     { 
      newItem.Next = prevItem.Next; 
      prevItem.Next = newItem; 
      newItem.Previous = currentItem.Previous; 
      currentItem.Previous = newItem; 
     } 
    } 
    public void Remove(object item) 
    { 
     int currentIndex = 0; 
     DoublyLinkedListNode currentItem = this.head; 
     DoublyLinkedListNode prevItem = null; 
     while (currentItem != null) 
     { 
      if ((currentItem.Element != null && 
       currentItem.Element.Equals(item)) || 
       (currentItem.Element == null) && (item == null)) 
      { 
       break; 
      } 
      prevItem = currentItem; 
      currentItem = currentItem.Next; 
      currentIndex++; 
     } 
     if (currentItem != null) 
     { 
      count--; 
      if (count == 0) 
      { 
       this.head = null; 
      } 
      else if (prevItem == null) 
      { 
       this.head = currentItem.Next; 
       this.head.Previous = null; 
      } 
      else if (currentItem == tail) 
      { 
       currentItem.Previous.Next = null; 
       this.tail = currentItem.Previous; 
      } 
      else 
      { 
       currentItem.Previous.Next = currentItem.Next; 
       currentItem.Next.Previous = currentItem.Previous; 
      } 
     } 
    } 
    public void RemoveAt(int index) 
    { 
     if (index >= this.count || index < 0) 
     { 
      throw new ArgumentOutOfRangeException("Out of range!"); 
     } 

     int currentIndex = 0; 
     DoublyLinkedListNode currentItem = this.head; 
     DoublyLinkedListNode prevItem = null; 
     while (currentIndex < index) 
     { 
      prevItem = currentItem; 
      currentItem = currentItem.Next; 
      currentIndex++; 
     } 
     if (this.count == 0) 
     { 
      this.head = null; 
     } 
     else if (prevItem == null) 
     { 
      this.head = currentItem.Next; 
      this.head.Previous = null; 
     } 
     else if (index == count - 1) 
     { 
      prevItem.Next = currentItem.Next; 
      tail = prevItem; 
      currentItem = null; 
     } 
     else 
     { 
      prevItem.Next = currentItem.Next; 
      currentItem.Next.Previous = prevItem; 
     } 
     count--; 
    } 
    public int indexOf(object item) 
    { 
     int index = 0; 
     DoublyLinkedListNode currentItem = this.head; 
     while (currentItem != null) 
     { 
      if (((currentItem.Element != null) && (item == currentItem.Element)) || 
       ((currentItem.Element == null) && (item == null))) 
      { 
       return index; 
      } 
      index++; 
      currentItem = currentItem.Next; 
     } 
     return -1; 
    } 
    public bool Contains(object element) 
    { 
     int index = indexOf(element); 
     bool contains = (index != -1); 
     return contains; 
    } 

    public void Clear() 
    { 
     this.head = null; 
     this.tail = null; 
     this.count = 0; 
    } 

    public object First() 
    { 
     if (this.count < 0) 
     { 
      throw new ArgumentOutOfRangeException("Out of range!"); 
     } 
     else 
      return this.head.Element; 
    } 

    public object Retrieve(int Position) 
    { 
     DoublyLinkedListNode current = this.head; 

     for (int i = 0; i < Position && current != null; i++) 
      current = current.Next; 
     return current; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 

     DoublyLinkedList Parts = new DoublyLinkedList(); 
     object element; 
     CarPart Part; 
     CarPart PartToFind; 

     Part = new CarPart(); 
     Part.PartNumber = 9743; 
     Part.PartName = "Air Filter"; 
     Part.UnitPrice = 8.75; 
     Parts.Add(Part); 

     Part = new CarPart(); 
     Part.PartNumber = 27487; 
     Part.PartName = "Clutch Disk"; 
     Part.UnitPrice = 47.15; 
     Parts.Add(Part); 

     Part = new CarPart(); 
     Part.PartNumber = 87873; 
     Part.PartName = "Brake Disk"; 
     Part.UnitPrice = 35.15; 
     Parts.Add(Part); 

     Part = new CarPart(); 
     Part.PartNumber = 27644; 
     Part.PartName = "A/C Filter Drier"; 
     Part.UnitPrice = 55.55; 
     Parts.Add(Part); 

     Console.WriteLine(" -=- Store Inventory -=-"); 
     Console.WriteLine("Number of Parts: {0}", Parts.Count); 

     object item = (object)Parts; 

     for (int i = 0; i < Parts.Count; i++) 
     { 
      // CarPart part = (CarPart)Parts.Retrieve(i); 
      element = Parts.Retrieve(i); 

      if (element != null) 
      { 
       // FAILS HERE AFTER RETRIEVING THE ELEMENT 
       CarPart part = (CarPart)element; 

       Console.WriteLine("\nCar Part Information"); 
       Console.WriteLine("Part #:  {0}", part.PartNumber); 
       Console.WriteLine("Description: {0}", part.PartName); 
       Console.WriteLine("Unit Price: {0:C}", part.UnitPrice); 
      } 
     } 
    } 
} 

我想要實現的是使用雙向鏈表來存儲許多不同的類型 - 向鏈表添加項目沒有問題,但我嘗試了很多不同的類型轉換方法,但都失敗了。

感謝任何意見,應該是一個簡單的問題來解決。

+0

通常會導致無效的投射異常 - 無論我嘗試使用哪種方式並將其投射出去! – Paul 2014-09-13 17:51:24

+2

今後,請儘量減少您發佈的代碼量,以滿足您的需求。例如,你永遠不會調用'Remove'或'RemoveAt',所以你可以通過刪除它們來簡化你的示例代碼。 (同上其他幾種方法。) – 2014-09-13 17:53:10

+0

泛型是您的問題的答案。通過這種方式,你可以強有力地鍵入你的類,並在編譯時揭示這樣的問題。 – 2014-09-13 17:55:20

回答

6

您的Retrieve方法返回節點本身 - 不是節點內的值,我假設它是您期望的值。這就是爲什麼你得到一個InvalidCastException。所有你需要改變的是從Retrieve

return current; 

最後一行

return current.element; 

我還強烈建議您讓DoublyLinkedList一個泛型類型(即DoublyLinkedList<T>),此時你贏了不需要投射,編譯時錯誤會很明顯。

+0

我推薦BCL中的'LinkedList '這是一個雙鏈表實現。 – 2014-09-13 17:54:38

+1

@SriramSakthivel:嗯,我認爲這是一個實施雙向鏈表的教育練習... – 2014-09-13 17:56:08

+0

謝謝大家的建議 - 它給了我更好/更清晰的做什麼...我有很多在Pascal中使用包括雙向鏈表的指針的經驗,但我還沒有在C#中構建一個類似的例子 - 儘管我可以(也許應該使用)內置的鏈表功能,但它只是試圖讓我的頭部繞過它一直在挑戰! – Paul 2014-09-14 15:00:43