473,386 Members | 1,793 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Nested generic collections

I can pass a generic collection as ICollection<Tjust fine:

static void flatCollection(ICollection<intc) {}

// ...

List<intl = new List<int>();
flatCollection(l); // Works fine

Now I want to pass nested collections generically:

static void nestedCollection(ICollection<ICollection<int>c) {}

List<List<int>l = new List<List<int>>();
nestedCollection(l); // Compile-time error

The compiler complains with:

Error 2 Argument '1': cannot convert from
'System.Collections.Generic.List<System.Collection s.Generic.List<int>>'
to
'System.Collections.Generic.ICollection<System.Col lections.Generic.ICollection<int>>'

This seems exceedingly strange. If I change the signature of
nestedCollection to:

static void nestedCollection(ICollection<List<int>c) {}

things work. But that defeats the purpose because now, I can no longer
generically pass collections of collections. What gives?

Cheers,

Michi.

Aug 28 '07 #1
5 4164
Michi Henning <mi***@zeroc.comwrote:
But that defeats the purpose because now, I can no longer
generically pass collections of collections. What gives?
It's exactly the same as why you can't use List<stringas a
List<object>.

Suppose your ICollection<ICollection<int>was actually a
List<List<int>at runtime. Using the interface version, someone could
add a LinkedList<intto it, at which point the type safety has been
broken.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Aug 28 '07 #2
On Aug 28, 4:30 pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
>
Suppose your ICollection<ICollection<int>was actually a
List<List<int>at runtime. Using the interface version, someone could
add a LinkedList<intto it, at which point the type safety has been
broken.
I'm sorry, I don't follow that. All the formal parameter types says is
that we have ICollection<intof ICollection<int>.
So, if someone add a few List<intand another few LinkedList<intto
the collections, what's broken? Both are ICollection<int>, so
everything would work fine, as far as I can see.

I just don't get it: I can pass a List<intas an ICollection<int>.
The receiver of the list knows that it is an ICollection<int>, so the
receiver cannot do anything but invoke ICollection operations on the
passed parameter (ignoring introspection and down-casts).

Now, if I have an ICollection<ICollection<int>>, why shouldn't the
same apply. The receiver gets a collection of collections. Some of the
elements of the outer collection might be List<int>, other elements
might LinkedList<int>, but so what? The receiver still can only invoke
operations on ICollection<inton the elements of the outer list.

I honestly can't see why this would break type safety in any way.

Cheers,

Michi.
>
--
Jon Skeet - <sk...@pobox.com>http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Aug 28 '07 #3
On Aug 28, 8:30 am, Michi Henning <mi...@zeroc.comwrote:
Suppose your ICollection<ICollection<int>was actually a
List<List<int>at runtime. Using the interface version, someone could
add a LinkedList<intto it, at which point the type safety has been
broken.

I'm sorry, I don't follow that. All the formal parameter types says is
that we have ICollection<intof ICollection<int>.
So, if someone add a few List<intand another few LinkedList<intto
the collections, what's broken? Both are ICollection<int>, so
everything would work fine, as far as I can see.
Correct, but look at your original code (variable renamed for
clarity):

List<List<int>lists = new List<List<int>>();
nestedCollection(lists);

That says that each element of lists is a List<int>. That means you
can't do:
lists.Add(new LinkedList<int>());
With me so far?

But suppose your nestedCollection method were written like this:

static void NestedCollection(ICollection<ICollection<int>c)
{
c.Add (new LinkedList<int>());
}

You'd be trying to add the LinkedList<intto a List<List<int>>. It's
fine as far as the NestedCollection method is concerned - there's
nothing problematic in that method - but it would still be breaking
type safety.
If you change your original declaration to:
List<ICollection<int>lists = new List<ICollection<int>>();
then it should be fine. At that point you're saying that you don't
care what each elements of "lists" is so long as it implements
ICollection<int>.

Jon

Aug 28 '07 #4
Michi Henning wrote:
On Aug 28, 4:30 pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
>Suppose your ICollection<ICollection<int>was actually a
List<List<int>at runtime. Using the interface version, someone could
add a LinkedList<intto it, at which point the type safety has been
broken.

I'm sorry, I don't follow that. All the formal parameter types says is
that we have ICollection<intof ICollection<int>.
(Well, actually it says you have an ICollection<of ICollection<int>,
or in other words an ICollection<ICollection<int>>. I think you knew
that, but just to be clear...)

Anyway, that's correct. That is _all_ it says.

Let's assume you're allowed to do what you want. That means that from
the point of view of the code within that method, it could put anything
into the ICollection<ICollection<int>as long as it's an
ICollection<int>. Any number of generic classes meet this requirement.

Jon's example was the LinkedList<intgeneric class. So, let's assume
that you pass a List<List<int>to the method. Then let's assume that
the method tries to add a LinkedList<intto the
ICollection<ICollection<int>in the method. This would be legal under
your suggested rules. Unfortunately, this would also allow your
List<List<int>(which is what was actually passed to the method and
which is the class being modified when you add the LinkedList<int>) to
contain a LinkedList<int>.

That violates the requirement that the List<List<int>only contain
instances of List<int>.
So, if someone add a few List<intand another few LinkedList<intto
the collections, what's broken?
If the original collection is a List<List<int>>, that's a serious
problem, to have a LinkedList<intas an element of the collection.
Both are ICollection<int>, so
everything would work fine, as far as I can see.
As far as the method knows, the items in the collection are only
ICollection<intinstances. The problem is that the collection is
really something else, and putting arbitrary ICollection<intinstances
into it can break the actual type of the collection.
I just don't get it: I can pass a List<intas an ICollection<int>.
Yes, that's true, you can. List<intimplements ICollection<intand so
it can be used anywhere that an ICollection<intis required.

But you can't pass a List<intas a List<objector an
ICollection<object>. And it is for the same reason. The issue here
isn't about whether the contained element is compatible with the
declared contained element in the method. It's whether the outer
collection itself is identical.
The receiver of the list knows that it is an ICollection<int>, so the
receiver cannot do anything but invoke ICollection operations on the
passed parameter (ignoring introspection and down-casts).
But the analog here isn't passing a List<intas an ICollection<int>.
The true analog would be passing a List<intas an ICollection<object>.
And that's not allowed.
Now, if I have an ICollection<ICollection<int>>, why shouldn't the
same apply. The receiver gets a collection of collections. Some of the
elements of the outer collection might be List<int>, other elements
might LinkedList<int>, but so what?
The problem isn't whether the method being called can safely use the
list. The problem is whether the list can be guaranteed to remain
correct relative to its actual type. That is, when the method is done,
can the caller expect the list to still only have List<intelements?

Because the method doesn't know anything about the type except the type
of the parameter, the answer to that question is no. The method could
have added anything that implements ICollection<intto the list,
including something other than a List<int(like the LinkedList<int>
that Jon mentioned).
The receiver still can only invoke
operations on ICollection<inton the elements of the outer list.
That's true. But it doesn't have anything to do with why you can't pass
the List<List<int>>
I honestly can't see why this would break type safety in any way.
I hope the above explains it satisfactorily.

Pete
Aug 28 '07 #5
On Aug 28, 5:59 pm, Peter Duniho <NpOeStPe...@NnOwSlPiAnMk.comwrote:
>
I hope the above explains it satisfactorily.
Yes, thanks--yours and John's explanation are perfectly clear. In
fact, I realized about ten minutes after posting my follow-up that the
problem is the Add() method on ICollection<T>. So, yes, it makes
sense.

I have to say though that this is a rather steep price to pay for the
lack of const-correctness. If methods could be marked const and could
be passed by const reference (as in C++), I wouldn't have this
problem.

Anyway, given the absence of const-correctness, it makes perfect
sense, thanks.

Cheers,

Michi.

Aug 28 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: B0nj | last post by:
I've got a class in which I want to implement a property that operates like an indexer, for the various colors associated with the class. For instance, I want to be able to do 'set' operations...
2
by: Jasper Kent | last post by:
I'm trying to do the equivalent of using typedefs with templates in C++ to avoid long instantiation names. I can do this okay: using BigDictionary = System.Collections.Generic.Dictionary<int,...
5
by: Atley | last post by:
I am trying to set up a nested collection so I can run statements like this: me.lblquestions.text = mysteps.item(1).questions(1).Asked Any ideas on how to do this? I have created a...
3
by: KH | last post by:
I can't seem to figure this one out... I've searched MSDN and Goog, and made my best guesses to no avail,, so help would be much appreciated! public ref class T sealed : public...
1
by: Morten Fagermoen | last post by:
Hi! I have the function below that return all users in a group, but this code does not work if there are nested groups. Can anyone tell me what to change to also get the users in the nested...
1
by: raylopez99 | last post by:
I seem to get name collision between the Generic collection SortedList and C++.NET Framework collection SortedList. How to resolve? Here are the libraries that seem to clash:...
2
by: Fred Heida | last post by:
Hi, i'm trying to (using managed C++) implment the IEnumerable<Tinterface on my class.. but have a problem with the 2 GetEnumerator method required.... what i have done is... ...
2
by: =?Utf-8?B?RGF2aWQgTW9ycmlz?= | last post by:
I am trying to create a nested Dictionary and get an error that seems odd to me. Here is my declaration: private IDictionary<Guid, IDictionary<Guid, string>> myNestedDictionary = new...
2
by: SimonDotException | last post by:
I am trying to use reflection in a property of a base type to inspect the properties of an instance of a type which is derived from that base type, when the properties can themselves be instances of...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.