Before posting my question, I would like to tell you that I have no prior experience in .Net technologies and have recently开发者_如何学编程 started to learn C# (and WPF). My company is looking to move onto .Net technologies and I am the only one in my team learning it, so have noone apart from you guys to discuss or ask something. So if my questions are too stupid or basic at best, please bear with me.
I was trying to create a generic linked list class to allow creation of linked lists of different types. I wrote the following code and would like to have your advise on whether I have written this code properly or not. Any suggestions to improve the code in any way is most welcome.
Main program
class Program
{
static void Main(string[] args)
{
GenLinkedList<string> list = new GenLinkedList<string>("abc");
list.AddtoList("def");
int i = 0;
string[] arr = new string[10];
list.LinkedList.CopyTo(arr,0);
for (i = 0; i < list.LinkedList.Count; i++)
{
Console.WriteLine(arr[i]);
}
GenLinkedList<int> listInt = new GenLinkedList<int>(1);
listInt.AddtoList(2);
i = 0;
int[] arrInt = new int[10];
listInt.LinkedList.CopyTo(arrInt, 0);
for (i = 0; i < listInt.LinkedList.Count; i++)
{
Console.WriteLine(arrInt[i]);
}
}
}
Class GenLinkedList
public class GenLinkedList<T>
{
private LinkedList<T> _linkedlist;
public GenLinkedList(T a)
{
_linkedlist = new LinkedList<T>();
_linkedlist.AddLast(a);
}
public LinkedList<T> LinkedList
{
get
{
return _linkedlist;
}
}
public void AddtoList(T a)
{
LinkedList.AddLast(a);
}
}
Why not use System.Collections.Generic.LinkedList<T>
? You're using it internally in your GenLinkedList<T>
already and it's already Generic for you.
It's the Framework Provided Generic Doubly Linked List implementation. Read up on it at:
MSDN - LinkedList(T) Class
If you're creating a Generic Linked List as an exercise, you shouldn't base your implementation of of an existing Generic Linked List. You're really not going to be learning anything by wrapping something that already does exactly what you need to do.
1
A generic linked list implementation already exists in the .NET framework: LinkedList<T>
. But you already know that; your code wraps it.
2
OK, so you know that. Why would you wrap it, then? The only functionality you appear to have implemented is AddtoList
, which doesn't do anything the LinkedList<T>
doesn't already do itself (after all, this is only a thin wrapper around LinkedList<T>.AddLast
). What this means is that your GenLinkedList<T>
class really doesn't offer the functionality of a linked list; it's basically an add-only collection (which could just as easily have been implemented with a List<T>
, or a Stack<T>
, or a Queue<T>
-- anything, really).
3
Assuming you do have a good reason to wrap a LinkedList<T>
(e.g., you're planning to add more functionality down the line that would actually leverage the behavior of a LinkedList<T>
and/or -- here's a key ingredient -- you want to restrict the way calling code is able to interact with the list (e.g., no removals)), you really shouldn't expose your LinkedList<T>
member at all. The purpose of a wrapper is just that: to wrap. You take an existing class and basically give it a new kind of interface. By exposing the underlying object directly, you cripple your wrapper. Any additional restrictions/validation/logic you have in your wrapper can be bypassed.
So, for example, if you want to be able to copy your list to an array, instead of doing this:
list.LinkedList.CopyTo(arr,0);
You would implement a CopyTo
method within your GenLinkedList<T>
class (which could simply call _linkedlist.CopyTo
) and use that.
But I really think the first question you should be asking yourself is what you want to accomplish by wrapping LinkedList<T>
in the first place.
The obvious question is why you don't just use LinkedList<T>
directly, although it looks like you're trying to emulate a singly-linked list.
In this case, you should avoid exposing the underlying LinkedList<T>
instance, since any client could manipulate it directly. I would also implement IEnumerable<T>
which will make your list usable by linq.
I got this from http://msdn.microsoft.com/en-us/library/0x6a29h6.aspx
Works fine with me.
namespace GenLinkedList
{
class Program
{
static void Main(string[] args)
{
GenericList<object> list = new GenericList<object>();
// Add items to list.
list.AddHead("some string here");
list.AddHead(DateTime.Today.ToLongDateString());
list.AddHead(13);
list.AddHead(13.005);
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Enumerate list.
foreach (object i in list)
{
Console.WriteLine(i + " " + i.GetType());
}
Console.WriteLine("\nDone");
}
}
}
namespace GenLinkedList
{
// type parameter T in angle brackets
class GenericList<T>
{
// The nested class is also generic on T.
public class Node
{
private Node next;
// T as private member data type.
private T data;
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
head = null;
}
// T as method parameter type
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
}
精彩评论