I'm looking to have a error raise to prevent a build if there are duplicate keys in my static Dictionary.
My current Dictionary below
public static readonly Dictionary<string, string> Fruits = new Dictionary<string, string>
{
{"Sobeys", "Apples"},
{"NoFrills", "Oranges"}
}
But lets say someone accidentally changes Sobeys to be Nofrills, I would like a compiler error to be raised to prevent anything to be done until that duplicate key is resolved. May I ask is that possible? If so how abouts would I do that?
public static readonly Dictionary<string, string> Fruits = new Dictionary<string, string>
{
{"NoFrills", "Apples"},
{"NoFrills", "Oranges"}
}
Nope, that's a runtime thing. As soon as the class is loaded into memory it will throw an exception (which are inherently runtime).
You could add a custom check through a diagnostic analyzer but that would be a lot of pain for very little gain. I suggest you just keep it as it is and keep an eye on any exceptions with a new deployment. You can always add a comment to make it clear to other devs that keys have to be unique but where do you stop? A developer is supposed to know basic framework rules like that.
You could also use, for example, an enum as the key which would make it clear at devtime when you try to add something that already exists. Another option is to refer to const string fields although it remains somewhat brittle.
You can also use the following hack (I do not recommend it): convert anonymous type to dictionary.
Anonymous types do not allow duplicate property names.
Example:
Dictionary<string, string> Fruits = ToDictionary(
new
{
Sobeys = "Apples",
NoFrills = "Oranges"
}
);
But this approach has the following limitation: you can have only valid identifiers as keys in your dictionary.
How to implement ToDictionary method is described there:
In c# convert anonymous type into key/value array?
C# compiler does not provide such possibility.
You will get an Exception at runtime.
To solve this, you have to implement your own pre-processing checks or handle runtime exceptions.
I would like an compiler error to be raised
It is not an error. That's why the compiler wan't issue a compile-time error. Collection initializer are syntactic sugar and are translated into respective Add() method (or indexer in case of the alternate syntax) calls.
Your best option is to rely on some 3rd party code analysis tool that can spot such potential errors.
Related
I'm new to C# and the .Net Framework 4.6. I do know Python, and I was wondering how to do something like this Python dictionary in C#:
GameData = {"VP":0, "Hamsters":"yes"};
I've already looked into C# dictionaries and arrays, that's not what I'm looking for. I want something that can be retrieved by something like this:
GameData["Hamsters"];
// Returns "yes"
Welcome to c#. Strong typing is a bitch. You do want a dictionary, but you need to specify the types of the key and value in the key value pairs during the instantiation of said dictionary. In your case, its string, and string.
Dictionary<string, string> yourDictionary = new Dictionary<string, string>();
Passing in these types in angle brackets after the type name is called generics in c#.
You can use the keyword 'var' to assume the implied type. Sometimes the implied type cannot be determined, and you must specify a type on the left hand side of the assignment operator. Thats not the case here though.
var yourDictionary = new Dictionary<string, string>();
You can also use a block at the end of the constructor to specify attributes or properties about the object.
var yourDictionary = new Dictionary<string, string>()
{
{"aKey", "aValue"},
{"anotherKey", "anotherValue"}
};
Now you should be able to access the values with
yourDictionary["aKey"];
and
yourDictionary["anotherKey"];
Careful though, because trying to get a key thats not there will throw an exception. Adding a duplicate key will also throw an exception. You can put the get calls in a try catch block
try{
yourDictionary["anotherKey"];
}
catch(Exception ex){
//do something with the error here
}
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 have a method
public static class PropertyLensMixins
{
public static ILens<Source> PropertyLens<O,Source>
( this O o
, Expression<Func<O, Source>> selector
)
where O: class, INotifyPropertyChanged
where Source: class, Immutable
{
return new PropertyLens<O, Source>(o, selector);
}
}
and the idea is to use it this way
this.PropertyLens(p=>p.MyProp)
however it is an error to create a nested expression even though the compiler will accept it
this.PropertyLens(p=>p.MyProp.NestProp)
now I can catch this at runtime by parsing the expression tree. For example
var names = ReactiveUI.Reflection.ExpressionToPropertyNames(selector).ToList();
if (names.Count > 1)
throw new ArgumentException("Selector may only be depth 1", "selector");
I was wondering however, is there any clever way to detect this at compile time? I doubt it because the compiler is happy with the type signature but I thought I might ask anyway.
I have also tried a Resharper pattern to match it as an error
$id0$.PropertyLens($id1$=>$id1$.$id2$.$id3$)
with all placeholders being identifiers but Resharper can't seem to match it.
There is no way to make the compiler reject such code.
One possible alternative would be to create a custom diagnostic using Roslyn. That way, all such errors will be marked by VS. Though it might be too much work for something like this.
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 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.