I wonder if there is an implementation of IDictionary interface in the standard library that has property IsFixedSize == true.
In my code, I am using a Dictionary indexed by an enum, like this:
Dictionary<EMyEnum, string> myDictionary = new Dictionary<EMyEnum, string>();
I always have values in the dictionary for all possible values of MyEnum, using a code like this:
foreach (EMyEnum myEnum in Enum.GetValues(typeof(EMyEnum)))
{
m_myDictionary.Add(myEnum, "");
}
so my dictionary actually has a fixed size. It feels kind of 'wrong' to be using Dictionary for it and I am wondering if there is perhaps a better type I am missing.
I was looking in System.Collections.Generic and System.Collections namespaces but could not find anything suitable.
In response to one of the questions, the enum is just a bunch of values, like this:
enum EMyEnum
{
meValue1,
meValue2,
meValue3
}
EDIT:
I have accepted supermem's answer as it is most to the point of the original question. To elaborate my original concern, an ordinary dictionary can have one of the keys/items deleted and then any code that relies on the fact that iterating over keys of the dictionary also iterates over all values of enum will be broken.
I understand that I can create a fixed size array but casting enums to ints is not that pretty, besides it would only work for contiguous enums (good enough in my case).
I think there is a good case for Dictionary that has enum values as keys and it is a pity that such a class does not ship with .Net.
.Net 4.5 actually introduces a new interface that sounds like it may be what you need, IReadOnlyDictionary<TKey, TValue>.
Also, IReadOnlyList<T>
No, there are no fixed size IDictionary implementations shipping with the CLR. (Except for the ReadOnly* sort, but not applicable to your problem.)
You can roll your own, but unless you have profiled this code and determined that the use of Dictionary presents a meaningful bottleneck (IMO, very rare), I'd say to keep it as is. You also have the benefit of readability as Dictionary is very well understood and easy to grok.
If you are using the simple enum declaration and not explicitly assigning values to the elements, you could use just an array:
Array values = Enum.GetValues(typeof(EMyEnum));
string[] myDictionary = new string[values.Length];
foreach (EMyEnum myEnum in values)
{
myDictionary[(int)myEnum] = "";
}
You could even wrap this approach in a custom class that treat the enum type as indexer, if you are bothered by those explicit casts to int everywhere:
class EnumDictionary<EnumType, ValueType>
{
private readonly ValueType[] array = new ValueType[Enum.GetValues(typeof(EnumType)).Length];
public ValueType this[EnumType index]
{
get { return array[Convert.ToInt32(index)]; }
set { array[Convert.ToInt32(index)] = value; }
}
}
EnumDictionary<EMyEnum, string> enumDictionary = new EnumDictionary<EMyEnum, string>();
foreach ( EMyEnum myEnum in Enum.GetValues(typeof(EnumType))
enumDictionary[myEnum] = "";
Now, if this is better than using Dictionary or not is a completely different discussion.
Related
I would like to create a list in C# that after its creation I won't be able to add or remove items from it. For example, I will create the list;
List<int> lst = a;
(a is an existing list), but after I won't be able to write the code (it will mark it as an error):
lst.Add(2);
.NET supports truly immutable collections, read-only views of mutable collections, and read-only interfaces implemented by mutable collections.
One such immutable collection is ImmutableArray<> which you can create as a.ToImmutableArray() in your example. Make sure to take a look at the other options MSDN lists because you may be better served by a different immutable collection. If you want to make copies of the original sequence with slight modifications, ImmutableList<> might be faster, for instance (the array is cheaper to create and access, though). Note that a.Add(...); is valid, but returns a new collection rather than changing a. If you have resharper, that will warn you if you ignore the return value of a pure method like Add (and there may be a roslyn extension to do something similar I'm unaware of). If you're going this route - consider skipping List<> entirely and going straight to immutable collections.
Read-only views of mutable collections are a little less safe but supported on older versions of .NET. The wrapping type is called ReadOnlyCollection<>, which in your example you might construct as a.AsReadOnly(). This collection does not guarantee immutability; it only guarrantees you can't change it. Some other bit of code that shares a reference to the underlying List<> can still change it. Also, ReadOnlyCollection also imposes some additional overhead; so you may not be winning much by avoiding immutable collections for performance reasons (TODO: benchmark this claim). You can use a read-only wrapper such as this even in a public API safely - there's no (non-reflection) way of getting the underlying list. However, since it's often no faster than immutable collections, and it's also not entirely safe, I recommend to avoid ReadOnlyCollection<> - I never use this anymore, personally.
Read-only interfaces implemented by mutable collections are even further down the scale of safety, but fast. You can simply cast List<> as IReadOnlyList<>, which you might do in your example as IReadOnlyList<int> lst = a. This is my preferences for internal code - you still get static type safety, you're simply not protected from malicious code or code that uses type-checks and casts unwisely (but those are avoidable via code-reviews in my experience). I've never been bitten by this choice, but it is less safe than the above two options. On the upside, it incurs no allocations and is faster. If you commonly do this, you may want to define an extension method to do the upcast for you (casts can be unsafe in C# because they not only do safe upcasts, but possibly failing downcasts, and user-defined conversions - so it's a good idea to avoid explicit casts wherever you can).
Note that in all cases, only the sequence itself is read-only. Underlying objects aren't affected (e.g. an int or string are immutable, but more complicated objects may or may not be).
TL;DR:
For safety: Use a.ToImmutableArray() to create an immutable copy in an ImmutableArray<int>.
For performance: Use IReadOnlyList<int> to help prevent accidental mutation in internal code with minimal performance overhead. Be aware that somebody can cast it back to List<> (don't do that), making this less "safe" for a public api.
Avoid a.AsReadOnly() which creates a ReadOnlyCollection<int> unless you're working on a legacy code base that doesn't support the newer alternatives, or if you really know what you're doing and have special needs (e.g. really do want to mutate the list elsewhere and have a read-only view).
You can use ImmutableList<T> / ImmutableArray<T> from System.Collections.Immutable NuGet:
var immutable = ImmutableList<int>.Create(1, 2, 3);
Or using the ToImmutableList extension method:
var immutable = mutableList.ToImmutableList();
In-case Add is invoked, *a new copy * is returned and doesn't modify the original list. This won't cause a compile time error though.
You need a ReadonlyCollection. You can create one from a list by calling List.AsReadOnly()
Reference: https://msdn.microsoft.com/en-us/library/ms132474.aspx
Why not just use an IEnumerable?
IEnumerable<string> myList = new List<string> { "value1", "value2" };
I recommend using a System.Collections.Immutable.ImmutableList<T> instance but referenced by a variable or property of type System.Collections.Generic.IReadOnlyList<T>. If you just use a naked immutable list, you won't get errors for adding to it, as you desire.
System.Collections.Generic.IReadOnlyList<int> list = a.ToImmutableList();
As an alternative to the already posted answers, you can wrap a readonly regular List<T> into an object that exposes it as IReadOnlyList.
class ROList<T>
{
public ROList(IEnumerable<T> argEnumerable)
{
m_list = new List<T>(argEnumerable);
}
private readonly List<T> m_list;
public IReadOnlyList<T> List { get { return m_list; } }
}
void Main()
{
var list = new List<int> {1, 2, 3};
var rolist = new ROList<int>(list);
foreach(var i in rolist.List)
Console.WriteLine(i);
//rolist.List.Add(4); // Uncomment this and it won't compile: Add() is not allowed
}
Your best bet here is to use an IReadOnlyList<int>.
The advantage of using IReadOnlyList<int> compared to List.AsReadOnly() is that a ReadOnlyCollection<T> can be assigned to an IList<T>, which can then be accessed via a writable indexer.
Example to clarify:
var original = new List<int> { 1, 2, 3 };
IReadOnlyList<int> readOnlyList = original;
Console.WriteLine(readOnlyList[0]); // Compiles.
readOnlyList[0] = 0; // Does not compile.
var readOnlyCollection = original.AsReadOnly();
readOnlyCollection[0] = 1; // Does not compile.
IList<int> collection = readOnlyCollection; // Compiles.
collection[0] = 1; // Compiles, but throws runtime exception.
Using an IReadOnlyList<int> avoids the possibility of accidentally passing the read-only list to a method which accepts an IList<> and which then tries to change an element - which would result in a runtime exception.
It could be IReadOnlyList<int>, e.g.
IReadOnlyList<int> lst = a;
So the initial list (a) is mutable while lst is not. Often we use IReadOnlyList<T> for public properties and IList<T> for private ones, e.g.
public class MyClass {
// class itself can modify m_MyList
private IList<int> m_MyList = new List{1, 2, 3};
...
// ... while code outside can't
public IReadOnlyList<int> MyList {
get {
return m_MyList;
}
}
}
Why not just:
readonly IEnumerable<int> lst = new List<int>() { a }
I am wondering about whether or not creating a list of an anonymous type is the best way to effectively create a list of multiple types as well as its effect on general performance and efficiency. Mainly I just want to know if there is a more standard way of doing List?
Situation
I every now and then find myself with a need to create a list that has multiple values each of a different type, List. Normally i would just resolve this with a Dictionary, but then there are the cases where i don't care about duplicated key values or need a 3rd (or rarely 4th) value. Usually this is for temporary list that just track something contained in a method like logging thrown errors and an associated value so that at the end of the method i can string together the messages for a log file or something.
What i have so far is this:
var list = new[] { new { RowNumber = 1, Message = "" } }.ToList();
list.Clear();//clears out the example used to create the anonymous type
list.Add(new { RowNumber = 10, Message = "bla bla" }); //adding to the list
I am debating on doing something like an extension or something to make this easier, but if the performance sucks or there is a better way, i would like to know.
I prefer to make a class. The IL just makes an anonymous class in native that gets called the same way as a normal class, so there is no performance hit associated with it. If you ever debug anonymous types, you'll notice the name has a long name like AnonymousTypes.Program+f__1
Creating a class improves the readability of your code IMO.
public class RowMessage
{
public int RowNumber { get; set; }
public string Message { get; set; }
}
You can also use Tuples, but even this is still unclear:
public void MyMethod()
{
Tuple<int, string> myTuple = new Tuple<int, string>(1, "hi");
List<Tuple<int, string>> myTupList = new List<Tuple<int, string>>();
myTupList.Add(myTuple);
}
I just experimented a little. Here's what I found:
Anonymous types are as good as anything else. I can't really say "anything," since I didn't try everything. But I can tell you that they're as good as Tuple<> and concrete types. This is logical, because underneath the covers, the compiler actually builds types for anonymous types. In essence, at runtime, they are just concrete types.
Your ToList call is redundant. This part's important. It's not super relevant to your immediate question, but looking at your example, you do new [] { ... }.ToList(). This forces a loop through the array after it's created. You'd be much better off using list initialization: new List<dynamic> { ... };. That's what I used in my examples.
I ran tests 10,000 times each for:
Anonymous type with array initializer (00:00:00.0050338 total)
Anonymous type with list initializer (00:00:00.0035599 total)
Tuple with list initializer (00:00:00.0025857 total)
Concrete type with list initializer (00:00:00.0041538 total)
Running them again would just mix it up. The only consistent result was that arrays were, unsurprisingly, slower than going directly to a list.
If you're going to make an extension method, you'll probably want to go with one of the latter two options. Anonymous types don't travel well outside of their scope, as I'm sure you know. The choice is yours between concrete types and tuples. I'd go with concrete if you're using it a lot and/or outside of the original method, and a tuple if it just needs to exist somewhere. That's really a design choice that I can't make for you.
Since you are talking about enriching Exceptioninformation it is worth to mention that the Exceptionclass implements a property called Data which is of type IDictionary and can be used to append additional information.
try
{
throw new FileNotFoundException{ Data ={ { "TEST", "Hello World" } } };
}
catch (Exception e)
{
Console.WriteLine(e.Data["TEST"]);
...
e.Data.Add("Whatever", DateTime.Now);
}
If you find yourself adding the same information lots of times, consider some HelperMethods that add certain information to a giving exception. This could also take care for duplicated keys which use some sort of numeric postfix that increments like fileName_1 and so on, you get the idea.
You can also create a standartized method of outputting those Information you provided yourself.
If you want a more Complex approach you can just simply use List but make the consumer of this list handle each kind of type. Which is basically the idea behind the DebuggerTypeProxy-Atrribute
So you can for example use some pattern like this:
foreach(var typeGroup in additionalInformation.GroupBy(item => item.GetType())
{
ITypedLogHandler handler = GetHandlerFor(typeGroup.Key);
handler.WriteLog(typeGroup);
}
In general the only reason I can think of this whole idea to beeing valid is some convenient debuggint/loggin approach. Anything else should really use strong typing.
I wanted to add a KeyValuePair<T,U> to a Dictionary<T, U> and I couldn't. I have to pass the key and the value separately, which must mean the Add method has to create a new KeyValuePair object to insert, which can't be very efficient. I can't believe there isn't an Add(KeyValuePair<T, U>) overload on the Add method. Can anyone suggest a possible reason for this apparent oversight?
You can use the IDictionary<TKey,TValue> interface which provides the Add(KeyValuePair<TKey,TValue>) method:
IDictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(new KeyValuePair<int,string>(0,"0"));
dictionary.Add(new KeyValuePair<int,string>(1,"1"));
Backup a minute...before going down the road of the oversight, you should establish whether creating a new KeyValuePair is really so inefficient.
First off, the Dictionary class is not internally implemented as a set of key/value pairs, but as a bunch of arrays. That aside, let's assume it was just a set of KeyValuePairs and look at efficiency.
The first thing to notice is that KeyValuePair is a structure. The real implication of that is that it has to be copied from the stack to the heap in order to be passed as a method parameter. When the KeyValuePair is added to the dictionary, it would have to be copied a second time to ensure value type semantics.
In order to pass the Key and Value as parameters, each parameter may be either a value type or a reference type. If they are value types, the performance will be very similar to the KeyValuePair route. If they are reference types, this can actually be a faster implementation since only the address needs to be passed around and very little copying has to be done. In both the best case and worst case, this option is marginally better than the KeyValuePair option due to the increased overhead of the KeyValuePair struct itself.
There is such a method – ICollection<KeyValuePair<K, T>>.Add but as it is explicitly implemented you need to cast your dictionary object to that interface to access it.
((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);
See
List of Explicit Interface Implementations on Dictionary<K, T>'s documentation page (you'll need to scroll down).
Explicit member implementation
The page on this method includes an example.
Should somebody really want to do this, here is an Extension
public static void Add<T, U>(this IDictionary<T, U> dic, KeyValuePair<T, U> KVP)
{
dic.Add(KVP.Key, KVP.Value);
}
but i would recommend to not do this if there is no real need to do this
Unless I'm mistaken, .NET 4.5 and 4.6 adds the ability to add a KeyValuePair to a Dictionary. (If I'm wrong, just notify me and I'll delete this answer.)
https://msdn.microsoft.com/en-us/library/cc673027%28v=vs.110%29.aspx
From the above link, the relevant piece of information is this code example:
public static void Main()
{
// Create a new dictionary of strings, with string keys, and
// access it through the generic ICollection interface. The
// generic ICollection interface views the dictionary as a
// collection of KeyValuePair objects with the same type
// arguments as the dictionary.
//
ICollection<KeyValuePair<String, String>> openWith =
new Dictionary<String, String>();
// Add some elements to the dictionary. When elements are
// added through the ICollection<T> interface, the keys
// and values must be wrapped in KeyValuePair objects.
//
openWith.Add(new KeyValuePair<String,String>("txt", "notepad.exe"));
openWith.Add(new KeyValuePair<String,String>("bmp", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("dib", "paint.exe"));
openWith.Add(new KeyValuePair<String,String>("rtf", "wordpad.exe"));
...
}
As can be seen, a new object of type Dictionary is created and called openWith. Then a new KVP object is created and added to openWith using the .Add method.
just because the enumerator for the Dictionary class returns a KeyValuePair, does not mean that is how it is implemented internally.
use IDictionary if you really need to pass KVP's because you've already got them in that format. otherwise use assignment or just use the Add method.
What would be wrong with just adding it into your project as an extension?
namespace System.Collection.Generic
{
public static class DictionaryExtensions
{
public static void AddKeyValuePair<K,V>(this IDictionary<K, V> me, KeyValuePair<K, V> other)
{
me.Add(other.Key, other.Value);
}
}
}
I'm not 100% sure, but I think the internal implementation of a Dictionary is a Hash-table, which means key's are converted to hashes to perform quick look ups.
Have a read here if you want to know more about hashtables
http://en.wikipedia.org/wiki/Hash_table
I'm using a Dictionary<int, MyType> in a class. That class implements a interface that requires an IList<MyType> to be returned. Is there a simple way to to cast the one to the other (without copying the entire thing)?
My current solution follows:
private IList<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection)
{
List<MyType> list = new List<MyType>();
list.AddRange(valueCollection);
return list;
}
You'll need to do a copy, but this is probably a good thing. In C# 2, your current code is almost the cleanest you can make. It would be improved by directly constructing your list off your values (List<MyType> list = new List<MyType>(valueCollection);), but a copy will still be required.
Using LINQ with C# 3, however, you would be able to do:
myDictionary.Values.ToList();
That being said, I would not (probably) try to avoid the copy. Returning a copy of your values tends to be safer, since it prevents the caller from causing problems if they attempt to modify your collection. By returning a copy, the caller can do list.Add(...) or list.Remove(...) without causing your class problems.
Edit: Given your comment below, if all you want is an IEnumerable<T> with a Count, you can just return ICollection<T>. This is directly implemented by ValueCollection, which means you can just return your dictionary's values directly, with no copying:
private ICollection<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection)
{
return valueCollection;
}
(Granted, this method becomes really useless in this case - but I wanted to demonstrate it for you...)
How about
Dictionary<int, MyType> dlist = new Dictionary<int, MyType>();
IList<MyType> list = new List<MyType>(dlist.Values);
This is not possible.
A dictionary (including its Values collection) is an inherently unordered collections; its order will change based on the hashcodes of its keys. This is why ValueCollection doesn't implement IList<T> in the first place.
If you really wanted to, you could make a wrapper class that implements IList and wraps the ValueCollection, using a foreach loop in the indexer. However, it's not a good idea.
You can use the constructor:
public IList<MyType> MyValues
{
get { return new List<MyType>(myDictionary.Values); }
}
(Edited to remove an assertion I'm not 100% sure on.)
You can use ToList() method:
myDictionary.Values.ToList();
It is available importing Linq: using System.Linq;
I am working with the static method
Enum.GetValues(typeof(SomeEnum));
This method works great when all you need to do is enumerate the values, but for some reason it returns a very simple form of the Array class. I am trying to find an easy way to turn it's return value into a more "normal" collection class like a regular array or List<>.
So far if I want to do that I have to enumerate through the output of Enum.GetValues(typeof(SomeEnum)); and add them one by one to a List<>.
Any ideas how to do this more cleanly?
Answer:
The key is to cast the return result --
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
If you need a List then jus wrap it in parenthesis and ToList it like so:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
If you're using .NET 3.5, you can also use Cast<T> and ToList extension methods.
IEnumerable<SomeEnum> enums = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
You can also get a list if you want to
List<SomeEnum> list = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();
Inspired by Jon Skeet's unconstrained-melody, I came up with version I like more:
public static class Enum<T>
where T: struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
Values = Array.AsReadOnly((T[])Enum.GetValues(typeof(T)));
}
public static readonly ReadOnlyCollection<T> Values;
}
and usage:
var values = Enum<BindingFlags>.Values;
Good thing is this version works faster for multiple calls because it does not create new array on every time.
I found here you can just do this:
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
And if you need a List just use .ToList() at the end, like this:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
Or if you like this better:
List<SomeEnum> list2 = new List<SomeEnum>((SomeEnum[]) Enum.GetValues(typeof(SomeEnum)));
I have a brand new library (UnconstrainedMelody) which helps with this. It can return the values in a strongly typed array or in an immutable list:
SomeEnum[] array = Enums<SomeEnum>.GetValuesArray()
IList<SomeEnum> list = Enums<SomeEnum>.GetValues();
It's generic and has a constraint on the type parameter to make sure it's genuinely an enum. This isn't possible in normal C#, but the library does a bit of furtling to make it work. I like the second form more, because we cache the list - the fact that it's immutable means we can return the same reference again and again.
There are various other utility methods to make it easier to work with flags enums etc.
Enjoy.
This should work:
List<MyEnum> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).ToList();
The reason ToList() didn't work in the solution you posted in your question was that you're missing a set of parens around the casted portion. Hope this helps!
REVISION (12-Sep-2009 ~2:20 PM EST):
So, I made this suggestion last night on the basis that Enum.GetValues returns an Array, and I thought that Array implements IEnumerable<T>:
I believe you can construct a
List<T> passing any IEnumerable<T>
as a parameter into the constructor.
So you should be able to just do this:
List<SomeEnum> values = new List<SomeEnum>(Enum.GetValues(typeof(SomeEnum)));
However, GordonG quite promptly replied to my answer indicating that it doesn't compile. (Ordinarily I would test my answer, but I was at a computer without any development tools at the time and was also feeling quite [unreasonably] sure of myself.)
After some downvotes and heavy soul-searching I resolved to get to the bottom of this matter (after a good night's sleep). Turns out, according to Microsoft's documentation on the Array class here, that Array does implement IEnumerable<T>, but only at run time (so, not at compile time--hence the failure to compile). This, in hindsight, makes sense: Enum.GetValues is not a generic method, and so it cannot know what sort of generic collection to return beforehand. (At least that's how I understand it.)
Anyway, what this all means is that you can legally cast an Array to an IEnumerable<T> provided that you get your type right. And so, at last I can present my final answer, which is really the same as my original answer but with a simple cast thrown in to make everything legal:
// splitting into two lines just for readability's sake
List<SomeEnum> values;
values = new List<SomeEnum>((IEnumerable<T>) Enum.GetValues(typeof(SomeEnum)));
Of course, in retrospect, GordonG wasn't dead set on getting a List<T>, which means his own answer of casting to SomeEnum[] is really just as good.
Updated solution (from 'Konstantin Spirin') for .NET framework 2.0:
public static class Enum<T> where T : struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
}
public static ReadOnlyCollection<T> Values = new ReadOnlyCollection<T>(((T[])Enum.GetValues(typeof(T))));
}
How about this:
List<SomeEnum> list = new List<SomeEnum>();
foreach (SomeEnum value in Enum.GetValues (typeof (SomeEnum)))
{
if (condition)
list.Add(value);
}