简体   繁体   中英

How to set a property of a class to be returned by default for an object/class?

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".

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>
}

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM