Reputation: 7169
I'm trying to implement my own list class. Just for training, to better understand how things work.
I have something like:
public class TestClass {
public int[] List;
// Add(), ...
}
I want to be able to retrieve the array (which is the property of TestClass
) like this:
var testClass = new TestClass();
int[] list = testClass; // without the ".List" list would point to the array
and not like this:
var testClass = new TestClass();
int[] list = testClass.List;
The same way that the c# build-in generic list class can be used.
How can i achieve this (if this is even possible)?
UPDATE
I changed the "list" to int[]
, i hope this will help.
I know that i could just do something like:
int[] list = new int[10];
But i needed the TestClass
because i needed some other (extended) properties about the array and more custom methods for it.
UPDATE 2
Maybe this will clear things up some more.
I'm trying to find out, how the generic List<T>
class works in this case:
var list = new List<T>();
foreach(var oneElement in list)
In my case i have to do it like this:
var list = new TestClass();
foreach(var oneElement in list.List)
I want to be able to retrieve my array the same way as the .NET
or C#
List<T>
class retrieves it's "underlying array".
Upvotes: 1
Views: 83
Reputation: 40808
To use your class in a foreach statement, you should implement IEnumerable<T>
. This is fairly straight-forward:
public class TestClass : IEnumerable<int>
{
private static readonly int[] Empty = new int[0];
public int[] List;
public IEnumerator<int> GetEnumerator()
{
int[] array = List == null ? Empty : List;
return array.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerator.GetEnumerator()
{
return GetEnumerator();
}
}
I added a simple null check in case List never gets assigned it will not throw when enumerating.
This allows you to use it in a foreach statement, as well as use LINQ extension methods:
var list = new TestClass();
foreach(var oneElement in list)
{
}
If you want other list like features you should probably implement IList<T>
. Also there is a base class, System.Collections.ObjectModel.Collection<T>
that implements all that for you. It has overridable methods so you can update other state in your class when items are added or removed. List<T>
has no overridable methods so its uses as a base class are limited.
Upvotes: 1
Reputation: 152501
DISCLAIMER
I add this only because the OP asked for it, but I don't think it's the appropriate solution in this (or most any other) situation.
I want to be able to get the list like this:
var testClass = new TestClass();
var list = testClass;
Well one problem is that you're using var
. The compiler will use the most reasonable type for list
, which is TestClass
, since that's what the type of testClass
is.
You could add a implicit casting operator if you wanted list
to be of a list type
public class TestClass<T> {
public T[] List ;
// ...
public static implicit operator List<T>(TestClass<T> t)
{
return t.List.ToList();
}
}
but then you'll have to specify the type of list
so that the compiler knows to cast the object:
var testClass = new TestClass<int>();
testClass.List = new[] {1,2,3,4};
List<int> list = testClass; // can't use `var here AND cast to List<T>
Also note that the "list" is read-only. You're retrieving a copy of the internal list. I suspect that you instead want to implement the interfaces (and all methods) methods that List<T>
implements rather then just exposing the underlying collection as a copy.
Upvotes: 0
Reputation: 1007
It sounds like you might want to create an indexer. You can do so as follows:
public class TestClass
{
public object this[int i]
{
get
{
// put your code here to return object i from the list
}
set
{
// put your code here to set object i in the list.
// A variable named "value" contains the incoming value.
}
}
}
You can now access items in the list as follows:
var testClass = new TestClass();
testClass[0] = 100; // any object really
var item = testClass[0];
You might also want to look at generic classes, which are useful when creating custom containers.
Upvotes: -1
Reputation: 14059
If var list
is allowed to have one of the types IEnumerable<T>
, ICollection<T>
or IList<T>
, then you just need to implement one of the interfaces IEnumerable<T>
, ICollection<T>
or IList<T>
:
public class TestClass : IList<SomeTypeOrGenericT>
{
public SomeTypeOrGenericT[] List;
// ...
// members of IList<SomeTypeOrGenericT>
}
Upvotes: 3