List interface: from Java to C# - c#

I'm a Java programmer learning C# these days.
Usually in Java when using lists, it should be preferrable programming against its interface in order to switch between implementations:
List<Object> list = new ArrayList<Object>();
//or
list = new LinkedList<Object>();
What about C# ? Does exist a similar approach? Can someone show me an example? Since now I'm building a list this way, but I don't think List is an interface:
List<int> list = new List<int>();
list.Add(2);

In .NET it is also preferable to work with the highest possible object in the hierarchy. You could use the IList<T> interface:
IList<int> list = new List<int>();
list.Add(2);
And if you don't need to access the list by index you could also use the ICollection<T> interface which is even higher in the hierarchy.
Or if you only want to enumerate through the list you could use the highest possible interface which is IEnumerable<T>:
IEnumerable<int> list = new List<int>(new[] { 1, 2, 3 });
foreach(int item in list)
{
...
}

IList<int> = new List<int>();
in C# it's easy - if it starts with an I its an interface.

List<T> implements a number of interfaces, including IList<T> and ICollection<T>. You may need to examine your code to determine which interface is most appropriate.

In .net IList<T> is the interface. And you can assign it any of the interface's implementations e.g., List<T>. See the implementations of this interface: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx#inheritanceContinued

Related

IList<IList<int>> doesn't accept List<List<int>>?

List implements IList so I expect IList will accept a List object
but why IList> doesn't accept List>?
static IList<int> List_1()
{
List<int> list = new List<int> { 1,2,3,3,4,5};
return list;
}
static IList<IList<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; //compiler error CS0266
}
That's because of
List<T> implements IList<T> but
List<List<T>> does not implement IList<IList<int>>
That's why your first method works as intended and second not.
Just change your declaration of the list in the second method to
List<IList<int>> parent = new List<IList<int>>();
And this is the case of covariance and contravariance.
Generic type parameters support covariance and contravariance but you need to define in that way
By learn.microsoft.com
Covariance and contravariance are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types
Suppose this works. Your client code is:
var result = List_2();
Since the contract allows adding to the result anything that's IList<int>, you could possibly have
public class MyCustomIList : IList<int>
{
...
}
and then
var result = List_2();
result.Add( new MyCustomIList() );
But that's wrong!
Your result is a list of List<int>, you should not be allowed to add anything other than List<int> or its derivatives there. However, you were able to add MyCustomIList which is not related to the List<int>.
If you need a broad picture of the issue, read more on covariance and contravariance.
The fundamental issue in this particular example comes from the Add operation. If you don't need it, the IEnumerable will do
static IEnumerable<IEnumerable<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; // no error, this works
}
This has been covered already.
Why then does List implement IList?
It is a bit odd, since List for any type other than object does not
fulfill the full contract of IList. It's probably to make it easier on
people who are updating old C# 1.0 code to use generics; those people
were probably already ensuring that only the right types got into
their lists. And most of the time when you're passing an IList around,
it is so the callee can get by-index access to the list, not so that
it can add new items of arbitrary type.
I would suggeste return IEnumerable instead of IList, will simplify your life, since List Fully implements it.
The problem is with your method return type. Modify your method signature to return to IList<List<int>> rather than returning IList<IList<int>>
static IList<List<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; //no compiler error
}
Now it will work fine as your method now returns an IList of List<int>
I don't know why you want to return exactly IList<IList<int>>, but one way of doing that is to use Cast<T>() method:
static IList<IList<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent.Cast<IList<int>>().ToList();
}
Or ConvertAll() method:
return parent.ConvertAll(x => (IList<int>)x);
Both methods will run over all elemets, and cast/convert them to a given type, so I think it would be better to return IList<List<int>> instead (if that's possible).

Easier way to systematically create new nodes?

So for testing purposes I need to have three IEnumerables of type <T>. One with both branches, one with one branch, and one comprising of just the node. I have to create further tests in much larger tree structures that will require more iterations of different IEnumerables. Currently, my (working) solution looks something like this. But I can't help but think that I could be adding the branches one at a time and setting the IEnumerables equal to one another at each step, or something of that nature to speed up the process. Evidently a direct implementation of this wouldn't work as they are reference types so they'll end up with the same value anyways, and it would be rather messy anyhow, if I worked around it...leaving me a bit stuck. Is there any way to accomplish this in less cumbersome fashion?
// Create test IEnumerables for comparison (one full, one with one branch, one of just node)
List<T> testlistfull, testlist1branch, testlistnode;
testlistnode = new List<T>();
testlistnode.Add(node0);
testlist1branch = new List<T>();
testlist1branch.Add(node0);
testlist1branch.Add(branch1);
testlistfull = new List<T>();
testlistfull.Add(node0);
testlistfull.Add(branch1);
testlistfull.Add(branch2);
IEnumerable<T> testenumfull = testlistfull as IEnumerable<T>;
IEnumerable<T> testenum1branch = testlist1branch as IEnumerable<T>;
IEnumerable<T> testenumnode = testlistnode as IEnumerable<T>;
You could use implicitly typed arrays. They infer their type from the values in the array initializer.
IEnumerable<T> testenumfull = new [] {node0, branch1, branch2};
IEnumerable<T> testenum1branch = new [] {node0, branch1};
IEnumerable<T> testenumnode = new [] {node0};
Or if they have to be of type List<T> for some reason.
IEnumerable<T> testenumfull = new List<T>{node0, branch1, branch2};
IEnumerable<T> testenum1branch = new List<T>{node0, branch1};
IEnumerable<T> testenumnode = new List<T>{node0};
You don't need the as IEnumerable<T> as simply assigning to a variable of that type will do the implicit cast.

C# .NET List declaration.Size unknown

I have to declare a list and use it in my code.How ever the number of elements that i will add to list will vary during each time I run my code.So how can I create a list and add elements to it dynamically with out specifying its size during declaration?
var myList = new List<string>();
myList.Add("foo");
myList.Add("blah");
// and on and on ...
List's in .Net will automatically resize themselves as you add to them.
You don't have to specify the bounds of a list (as you do with arrays). You can keep on calling Add() method to add elements in the list. You can create either a generic list which takes only specified types of objects and a non-generic list that only takes objects:
Generic:
List<int> intList = new List<int>();
intList.Add(10);
intList.Add(20);
Non-Generic:
ArrayList objList = new ArrayList();
objList.Add(New Employee());
objList.Add(20);
objList.Add("string");
The later can take any type of object but is not type-safe.
The System.Collection namespace is full of collection classes that can dynamically contract and expand its size, see the Generic namespace for the most used classes: http://msdn.microsoft.com/en-us/library/system.collections.generic.aspx
I recommend sticking with a List if you doubt what you are doing:
var list = new List<string>();
list.Add("test1");
list.Add("test2");
list.Remove("test1");

Multiple objects in list, C#

I'm looking for something similar to List<T>, that would allow me to have multiple T. For example: List<TabItem, DataGrid, int, string, ...> = new List<TabItem, DataGrid, int, string, ...>().
If you are using .NET 4, you could have a List<Tuple<T1, T2, ...>>
Otherwise, your choice is to implement your own type.
Create a class that defines your data structure, and then do
var list = new List<MyClass>();
Normally you'd just have List<MyClass> where MyClass had all those other ones as members.
If it can have any old type, then you need to use an ArrayList.
If you know ahead of time what you'll have in there, then you should either create your own structure, or use a Tuple.
Looks like you're after List<object>?
Tuples are best if you are using .net 4.0. But if you are working 3.5 or below, multidimensional object array is good. Here is the code. I have added 3 different types in a object array and I pushed the same to list. May not be the best solution for your question, can be achieved with object array and list. Take a look at the code.
class Program
{
static void Main(string[] args)
{
object[,] OneObject = new object[1,3]{ {"C Sharp",4,3.5 }};
List<object> MyList = new List<object>();
MyList.Add(OneObject);
object[,] addObject = new object[1,3]{{"Java",1,1.1}};
MyList.Add(addObject);
foreach(object SingleObject in MyList)
{
object[,] MyObject = (object[,])SingleObject;
Console.WriteLine("{0},{1},{2}", MyObject[0, 0], MyObject[0, 1], MyObject[0, 2]);
}
Console.Read();
}
}
Instead of trying in C# 4, you can give the old version features a chance here.
It seems you don't need a strongly typed collection here, in that case ArrayList is the best option.

IList<Type> to IList<BaseType>

I have a few classes:
class Vehicle
{
}
class Car : Vehicle
{
}
I have a list of the derived class:
IList<Car> cars;
I would like to convert the list to its base class, and have tried:
IList<Vehicle> baseList = cars as IList<Vehicle>;
But I always get null. Also
cars is IList<Vehicle> evaluates to be false.
Granted, I can add the items to a list if I do the following:
List<Vehicle> test = new List<Vehicle> ();
foreach ( Car car in cars )
{
test.Add(car);
}
And I get my list, but I know there has to be a better way.
Any thoughts?
Use IEnumerable<T>.Cast :
IList<Vehicle> vehicles = cars.Cast<Vehicle>().ToList();
Alternatively, you may be able to avoid the conversion to List depending on how you wish to process the source car list.
That sort of polymorphism that lets you cast IList<Car> to IList<Vehicle> is unsafe, because it would let you insert a Truck in your IList<Car>.
You're facing the problem that there is limited co- and contravariance in C#. There is an interesting approach in C# 4.0, described here at the very ending. However, it creates some other limitations that are related to the truck-problem in the answer from Novelocrat.
Here are a couple of approaches using Linq:
IList<Derived> list = new List<Derived>();
list.Add(new Derived());
IList<Base> otherlist = new List<Base>(from item in list select item as Base);
IList<Base> otherlist2 = new List<Base>(list.Select(item => item as Base));
You can also take a look on Krzysztof's Cwalina article, Simulated Covariance for .NET Generics
var vehicles = cars.OfType<IVehicle>()
If you must use IList all of the way, then you are out of luck and the answers above can help you. However, if you can use an IList that is casted as IEnumerable and then simply re-casted at the destination as IList, that would work, since IEnumerable can accept such practice.
// At the source or at the model.
IEnumerable<BaseType> list = new List<Type>();
// At the destination.
IList<BaseType> castedList = (IList<BaseType>)list;
Although, since the compiler cannot enforce these things, you must manually make sure that the types and base types indeed match, of course.
Note that IReadOnlyList<T> from .NET 4.5+ will allow you to cast IReadOnlyList<Car> into IReadOnlyList<Vehicle> with no problems. List<T> and Collection<T> implement this interface.

Categories

Resources