467,925 Members | 2,023 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 467,925 developers. It's quick & easy.

Converting a Dictionary to an array?

This is two questions in one really. First, I wonder how to convert the
values in a Dictionary to an array. Here's the dictionary:

private Dictionary<Uri, Schemaschemas = new Dictionary<Uri, Schema>();

Uri is the System.Uri class, and Schema is a class I made. Now, I want
the class where this Dictionary is contained to have a property that
returns all the values in this Dictionary. Like such:

public Schema[] Schemas

How do I implement this property? I can figure out how to do it, but
that involves looping through all the elements in the dictionary, and
that's probably not the way it's meant to be done. I assume there must
be a one-liner solution, like the ArrayList.ToArray() method. I found
the Dictionary.Values property, but can't figure out how to make that
into an array.

My second question is about best practices. I wonder if it makes sense
to have a property that returns an array of Schema objects, rather than
returning another kind of collection? I want a basic and general
interface outwards, something that doesn't assume too much in terms of
what packages are used in the calling class. Then, is an object array
the best choice?

Gustaf
Dec 18 '06 #1
  • viewed: 32788
Share:
20 Replies
Hi Gustaf,
This is two questions in one really. First, I wonder how to convert the
values in a Dictionary to an array. Here's the dictionary:

private Dictionary<Uri, Schemaschemas = new Dictionary<Uri, Schema>();

Uri is the System.Uri class, and Schema is a class I made. Now, I want the
class where this Dictionary is contained to have a property that returns
all the values in this Dictionary. Like such:

public Schema[] Schemas

How do I implement this property? I can figure out how to do it, but that
involves looping through all the elements in the dictionary, and that's
probably not the way it's meant to be done. I assume there must be a
one-liner solution, like the ArrayList.ToArray() method. I found the
Dictionary.Values property, but can't figure out how to make that into an
array.
public Schema[] Schemas
{
get
{
Schema[] array = new Schema[schemas.Count];
schemas.Values.CopyTo(array, 0);
return array;
}
}
My second question is about best practices. I wonder if it makes sense to
have a property that returns an array of Schema objects, rather than
returning another kind of collection? I want a basic and general interface
outwards, something that doesn't assume too much in terms of what packages
are used in the calling class. Then, is an object array the best choice?
That depends on what the caller will be doing with the return value, but
most likely an array would be your best choice since it only represents a
copy of the values in your dictionary. Any other return type might be
misleading.

--
Dave Sexton
Dec 18 '06 #2
Gustaf <gu*****@algonet.sewrote:
>I found the Dictionary.Values property, but can't figure out how to make that
into an array.
My second question is about best practices. I wonder if it makes sense
to have a property that returns an array of Schema objects, rather than
returning another kind of collection? I want a basic and general
interface outwards, something that doesn't assume too much in terms of
what packages are used in the calling class. Then, is an object array
the best choice?
I don't think an object array is the best choice. Dictionary.Values
seems perfect for what you need. And I think it's more elegant for
objects to return ICollection<Tor IEnumerable<Trather than T[].
(e.g. returning an IEnumerable<Twould let you completely rewrite
your code for returning the thing, perhaps even using the wonderful
"yield return").

--
Lucian
Dec 18 '06 #3
Gustaf wrote:
public Schema[] Schemas

How do I implement this property? I can figure out how to do it, but
that involves looping through all the elements in the dictionary, and
that's probably not the way it's meant to be done. I assume there must
be a one-liner solution, like the ArrayList.ToArray() method. I found
the Dictionary.Values property, but can't figure out how to make that
into an array.
You can do this as a one-liner, but it's not pretty:

return new List<Schema>(schemas.Values).ToArray();

If you don't want to get fired after your next code review, you
probably ought to break this into two statements:

List<SchemaValues = new List<Schema>(schemas.Values);
return Values.ToArray();
My second question is about best practices. I wonder if it makes sense
to have a property that returns an array of Schema objects, rather than
returning another kind of collection? I want a basic and general
interface outwards, something that doesn't assume too much in terms of
what packages are used in the calling class. Then, is an object array
the best choice?
Probably not. The approach that makes the fewest assumptions and
wastes the fewest cycles is to just expose a

public IEnumerable<SchemaValues
{
get { return schemas.Values; }
}

Then, if your callers just want to enumerate, they can do so without
any waste of time or memory. If they want a List<Schema>, they can
easily generate one; ditto if they want a Schema[].

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Dec 18 '06 #4
"Jon Shemitz" <jo*@midnightbeach.comwrote in message
news:45***************@midnightbeach.com...
You can do this as a one-liner, but it's not pretty:

return new List<Schema>(schemas.Values).ToArray();

If you don't want to get fired after your next code review
I've never understood that attitude at all - there is absolutely *nothing*
wrong with that single line of code...
Dec 18 '06 #5
Hi Mark,

Well, it's iterating the entire collection to copy it into a new object,
just so it can do another copy internally again to return it as an array,
simply to save 2 lines of code :)

--
Dave Sexton

"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:OC**************@TK2MSFTNGP04.phx.gbl...
"Jon Shemitz" <jo*@midnightbeach.comwrote in message
news:45***************@midnightbeach.com...
>You can do this as a one-liner, but it's not pretty:

return new List<Schema>(schemas.Values).ToArray();

If you don't want to get fired after your next code review

I've never understood that attitude at all - there is absolutely *nothing*
wrong with that single line of code...

Dec 18 '06 #6
Mark Rae wrote:
You can do this as a one-liner, but it's not pretty:

return new List<Schema>(schemas.Values).ToArray();

If you don't want to get fired after your next code review

I've never understood that attitude at all - there is absolutely *nothing*
wrong with that single line of code...
It's sort of hard to parse, especially if you're a bit unclear on C#
operator precedence. And, imho, you can be a perfectly fine C#
programmer - comfortable with all the operators and idioms - and still
be a bit unclear on C# operator precedence. I mean **15** levels of
precedence? It makes a lot of sense to ignore that and use
"unnecessary" parens.

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Dec 18 '06 #7
Dave Sexton wrote:
Well, it's iterating the entire collection to copy it into a new object,
just so it can do another copy internally again to return it as an array,
simply to save 2 lines of code :)
Yeah - I was typing under the influence of the impression that Keys
and Values were IEnumerable<T>s, not collections. (It certainly seems
like that would be a better design.)

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Dec 18 '06 #8

"Dave Sexton" <dave@jwa[remove.this]online.comha scritto nel messaggio
news:eX**************@TK2MSFTNGP06.phx.gbl...
Hi Mark,

Well, it's iterating the entire collection to copy it into a new object,
just so it can do another copy internally again to return it as an array,
simply to save 2 lines of code :)
Premised that I also prefere the second solution, I really don't see
difference into generated IL.
I would be more worried about the fact that a class shouldn't return a
Something<Tclass to the extern.

Dec 18 '06 #9
"Fabio Z" <zn*******@virgilio.itwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
Premised that I also prefere the second solution,
That's perfectly fine, but a very different argument...:-)
I really don't see difference into generated IL.
That's because there isn't any, AFAICS
I would be more worried about the fact that a class shouldn't return a
Something<Tclass to the extern.
:-)
Dec 18 '06 #10
"Mark Rae" <ma**@markNOSPAMrae.comha scritto nel messaggio
news:OO**************@TK2MSFTNGP06.phx.gbl...
>I really don't see difference into generated IL.

That's because there isn't any, AFAICS
so... where is the problem? :)
Dec 18 '06 #11
Hi Fabio,
>Well, it's iterating the entire collection to copy it into a new object,
just so it can do another copy internally again to return it as an array,
simply to save 2 lines of code :)
Premised that I also prefere the second solution, I really don't see
difference into generated IL.
The IL is certainly different. Consider what's inside of the List<T>
constructor. The parameter being supplied is IEnumerable<T>, used to copy
the entire collection into the new List<Tobject. Then, another method
call is made (ToArray) to perform a similar operation as the code that I
supplied does in 2 lines of code.

The difference is that a new object is created (List<T>) and an extra
iteration over the entire collection occurs (inside its constructor), which
could be costly if the collection is large or the operation is performed
many times.
I would be more worried about the fact that a class shouldn't return a
Something<Tclass to the extern.
Why? Haven't you returned IEnumerable<Tfrom a property before, or any
generic type for that matter?

In this particular situation I think returning an Array is probably the best
choice, but if the OP decided that consumers of the class would be better
off having an IEnumerable<Tor ICollection<T>, with very good reason, then
that should be acceptable. The reason why I think Array is better is
because IEnumerable<Tmay give the impression that the collection of
Schemas can always be iterated in the same order, which is false since the
OP is using a Dictionary (IIRC). ICollection<Tcan be modified, which
gives the impression that the Schemas property itself will change, but it
won't since it's being backed by the values of a dictionary. Both are
misleading to callers.

I usually assume a property that returns an Array to be a copy of the values
stored within a class, which isn't misleading to callers since that's what
the OP requires. It's IEnumerable and If consumers require a collection
they can fill a List<T>, just like in the one-line example that you prefer
(although it would be external to the class and so caller's choice).

--
Dave Sexton
Dec 18 '06 #12
"Dave Sexton" <dave@jwa[remove.this]online.comha scritto nel messaggio
>Premised that I also prefere the second solution, I really don't see
difference into generated IL.

The IL is certainly different.
Really different :)
I did a test, and the second solution produces EXACTLY the same IL (except
the fact that a second variabe and a call reference to it are created, so
the first solution would be even optimized).

>I would be more worried about the fact that a class shouldn't return a
Something<Tclass to the extern.

Why? Haven't you returned IEnumerable<Tfrom a property before, or any
generic type for that matter?
Because it is a bad practice.
You should expose a

class MyTypeCollection : List<MyType{}

instead of a List<MyType>.

Dec 18 '06 #13
"Fabio Z" <zn*******@virgilio.itha scritto nel messaggio
news:OV**************@TK2MSFTNGP03.phx.gbl...

I did a test, and the second solution produces EXACTLY the same IL
And it seems logical to me.
Dec 18 '06 #14
Hi Fabio,
>>Premised that I also prefere the second solution, I really don't see
difference into generated IL.

The IL is certainly different.

Really different :)
I did a test, and the second solution produces EXACTLY the same IL (except
the fact that a second variabe and a call reference to it are created, so
the first solution would be even optimized).
I'm really not sure what you mean here. There is definitely a difference
between the two examples both in the IL that is produced and in the IL that
is executed. You shouldn't base your opinion solely on the IL that is
produced anyway - it's the IL being processed that makes the important
difference in this case.
>>I would be more worried about the fact that a class shouldn't return a
Something<Tclass to the extern.

Why? Haven't you returned IEnumerable<Tfrom a property before, or any
generic type for that matter?

Because it is a bad practice.
You should expose a

class MyTypeCollection : List<MyType{}

instead of a List<MyType>.
I disagree that using a generic type as a property is bad practice.

When I need to expose a list of items from a class I may return an IList<T>
(not a concrete implementation, although I don't think that's particularly
important). Wrapping every list returned by a property in a custom
collection is overkill unless you need to extend the default behavior, IMO.

And you lose type-safety if you return IEnumerable over IEnumerable<T>, for
example.

--
Dave Sexton
Dec 18 '06 #15
"Dave Sexton" <dave@jwa[remove.this]online.comwrote:
>In this particular situation I think returning an Array is probably the best
choice, but if the OP decided that consumers of the class would be better
off having an IEnumerable<Tor ICollection<T>, with very good reason, then
that should be acceptable. The reason why I think Array is better is
because IEnumerable<Tmay give the impression that the collection of
Schemas can always be iterated in the same order, which is false since the
OP is using a Dictionary (IIRC). ICollection<Tcan be modified, which
gives the impression that the Schemas property itself will change, but it
won't since it's being backed by the values of a dictionary. Both are
misleading to callers.
I don't think IEnumerable<Tis misleading. After all,
Dictionary.Values returns an IEnumerable without the order-guarantee
you're reading.

As for ICollection, the advice from FxCop is to wrap it up inside a
ReadOnlyCollection<Twhen you return it. That seems fine.

--
Lucian
Dec 18 '06 #16
Hi Lucian,
I don't think IEnumerable<Tis misleading. After all,
Dictionary.Values returns an IEnumerable without the order-guarantee
you're reading.
But that's on a Dictionary, which already has specific semantics for which
you are aware. What if you saw IEnumerable<Schemaon some arbitrary class
and you didn't (and probably shouldn't) know that the class was using a
Dictionary internally? Returning an Array is much clearer, IMO.

Another reason why I prefer Array over IEnumerable<Twhen returning a list
of values is because Array can be cast to IEnumerable<Tanyway.

Also, IEnumerable<Tis usually not enough for consumers since consumers
generally require a list, not an iterator (although with the constructors of
generic collections taking IEnumerable<Tin 2.0, I might have to change my
opinion on this point :)
As for ICollection, the advice from FxCop is to wrap it up inside a
ReadOnlyCollection<Twhen you return it. That seems fine.
Yes, that seems like good advice, although returning an Array is just as
good and more common, IMO.

--
Dave Sexton
Dec 18 '06 #17

"Dave Sexton" <dave@jwa[remove.this]online.comha scritto nel messaggio
news:%2****************@TK2MSFTNGP02.phx.gbl...

I'm really not sure what you mean here. There is definitely a difference
between the two examples both in the IL that is produced and in the IL
that is executed.
if 1 produces A and 2 produces A I don't know what is the doubt about if
will be executed A rather than A :)

I disagree that using a generic type as a property is bad practice.

When I need to expose a list of items from a class I may return an
IList<T(not a concrete implementation, although I don't think that's
particularly important). Wrapping every list returned by a property in a
custom collection is overkill unless you need to extend the default
behavior, IMO.
It's good if you expose a class MyClass<T>, but you should not return
MyClass<Tto the extern.
So as it's not elegant to return a List<T>.

And you lose type-safety if you return IEnumerable over IEnumerable<T>,
for example.
This is not the same.
I told to expose

IMyBaseClassEnumerable : IEnumerable<MyBaseClass>

I think you have a base class that is not object ;)
Dec 18 '06 #18
Hi Fabio,
>I'm really not sure what you mean here. There is definitely a difference
between the two examples both in the IL that is produced and in the IL
that is executed.

if 1 produces A and 2 produces A I don't know what is the doubt about if
will be executed A rather than A :)
Well, I've explained it three times already so I really don't know what
other evidence there is to submit. Yes, the two solutions both have the
same outcome, but how they get there is quite different.

<snip>

--
Dave Sexton
Dec 18 '06 #19
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:eh**************@TK2MSFTNGP02.phx.gbl...
Hi Fabio,
>if 1 produces A and 2 produces A I don't know what is the doubt about if
will be executed A rather than A :)

Well, I've explained it three times already so I really don't know what
other evidence there is to submit. Yes, the two solutions both have the
same outcome, but how they get there is quite different.

<snip>

--
Dave Sexton
Having read this thread - I'm going to throw out that I think you guys are
talking about two different sets of code :)

I *think* Fabio is referring to the following examples given by Jon Shemitz:

return new List<Schema>(schemas.Values).ToArray();

vs

List<SchemaValues = new List<Schema>(schemas.Values);
return Values.ToArray();

To which, I would agree they probably generate the same IL.

Dave, I think you are referring to what you originally posted:
Schema[] array = new Schema[schemas.Count];
schemas.Values.CopyTo(array, 0);
return array;

vs

What Jon posted.

To which I also agree - the first is more effecient as it does not have to
iterate across the collection twice.

--
Adam Clauss
Dec 18 '06 #20
Hi Adam,

Lol - thanks for clearing that up :)

I guess Fabio assumed that I was speaking about different code in my
original response to Mark Rae. When I wrote, "simply to save 2 lines of
code", I was referring to the two lines of code in my example. I think the
problem stemmed from the fact that Mark didn't quote Jon completely and then
I addressed his point in terms of the OPs question. This is why I think
statements should be addressed in complete contexts, not arbitrary excerpts.

Thanks again for pointing that out - it was really throwing me for a loop.

--
Dave Sexton

"Adam Clauss" <ca*****@tamu.eduwrote in message
news:12*************@corp.supernews.com...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:eh**************@TK2MSFTNGP02.phx.gbl...
>Hi Fabio,
>>if 1 produces A and 2 produces A I don't know what is the doubt about if
will be executed A rather than A :)

Well, I've explained it three times already so I really don't know what
other evidence there is to submit. Yes, the two solutions both have the
same outcome, but how they get there is quite different.

<snip>

--
Dave Sexton

Having read this thread - I'm going to throw out that I think you guys are
talking about two different sets of code :)

I *think* Fabio is referring to the following examples given by Jon
Shemitz:

return new List<Schema>(schemas.Values).ToArray();

vs

List<SchemaValues = new List<Schema>(schemas.Values);
return Values.ToArray();

To which, I would agree they probably generate the same IL.

Dave, I think you are referring to what you originally posted:
Schema[] array = new Schema[schemas.Count];
schemas.Values.CopyTo(array, 0);
return array;

vs

What Jon posted.

To which I also agree - the first is more effecient as it does not have to
iterate across the collection twice.

--
Adam Clauss

Dec 18 '06 #21

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by What-a-Tool | last post: by
2 posts views Thread by jg | last post: by
18 posts views Thread by =?Utf-8?B?VHJlY2l1cw==?= | last post: by
8 posts views Thread by Bob Altman | last post: by
1 post views Thread by Gilles Ganault | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.