I want to create a container class which works like a kind of Directory, but with multiple keys and the possibility to assign several values to one key. The number of possible keys should be variable. I want to do that through creating for every key-Type in inputTypes a new Dictionary which contains the key and the index of the value in the values' list.
class SampleContainer<Tvalue>
{
public SampleContainer(params Type[]inputTypes)
{
foreach(Type t in inputTypes)
{
ls.Add(new Dictionary(t,int));//won't compile
}
values=new List<Tvalue>();
}
List<Dictionary< ???,int>> ls;/*object as ??? doesn't work,
what to fill in to keep it "generic"*/
List<Tvalue>values;
}
Try
List<IDictionary> ls = new List<IDictionary>();
ls.Add(typeof(Dictionary<,>).MakeGenericType(typeof(int), typeof(bool))
.GetConstructor(Type.EmptyTypes)
.Invoke(null) as IDictionary);
There are side-effects though, the IDictionary interface uses object key/value pairs. It may also cause boxing when attempting to retrieve a value (because it returns object types).
Maybe somebody can think of a really neat way to do it and keep the strong typing, but this is the closest I can think to come to what you are asking to do.
Related
I have been doing a lot of research, and I can't seem to find an answer that will work for me. I have a dictionary that holds the values of all of my global game variables/states (things like inventory item picked up, etc.), and it is setup up like Dictionary<string, object> because certain variables are bools, while others are strings, ints, etc.
My question is: While iterating through the dictionary, how do I differentiate between them to determine which is a bool, string, etc? I have tried something like:
foreach (string key in GlobalGameVars.globals.Keys.ToList())
{
if (GlobalGameVars.globals[key].GetType() == typeof(bool))
// Do something
}
Unfortunately, it tells me object type and bool type don't match. Which makes sense, but is there any way to use an object and then test its underlying type?
Or is there an even better way to go about this that would allow me to forgo the use of generic object type?
Any help would be much appreciated. Thanks!
That logic should work. For example, this runs fine in linqpad:
var foo = new List<object>();
foo.Add("123");
foo.Add(123);
foo.Add(false);
foreach (var thing in foo)
{
if (thing.GetType() == typeof(bool))
{
"I found a bool".Dump();
}
else
{
"Not a bool".Dump();
}
}
Run that and you'll get:
Not a bool
Not a bool
I found a bool
But to answer your question, you might be better off creating a Dictionary<string, IGameValue> where IGameValue is an interface you define. Each implementation of that interface (say BooleanGameValue) would have whatever arbitrary information it needs, but also always expose the information that you need in your game loop code.
Specifically I am trying to create a dictionary with keys of type PropertyInfo and a value that is a List that I would like to enforce as containing objects of the same type as the associated Property described by the key. In other words, a dictionary that describes a set of properties and values to assign to them.
I know that I can simply use a list of Objects, but as far as I can tell, that forces me to perform my check for validity of the contained list types at run-time and also forces me to check every member of the list.
Ideally, I'd instead like this to be enforced at compile time rather than run time and/or to remove the need for verifying ever individual member of the list. I am ok with getting a compile time error if the compiler cannot actually determine the property's type at compile time (my particular use case deals with properties that will be known).
I suspect this may not be possible due to the issue of the compiler not having a way to always be certain of the type that the property will have prior to run time, but I'm hoping I missed something that may allow for it.
You haven't missed anything. It's impossible since there is no property type info associated with PropertyInfo at compile time. It's even not a generic type (like List<T>).
You can create a Dictionary<PropertyInfo, dynamic>, but it's not going to be able to be checked at compile time. You can create a value for a given key by doing:
class MyClass
{
public int Property { get; set; }
}
var dict = new Dictionary<PropertyInfo, dynamic>();
var propertyInfo = typeof(MyClass).GetProperty(nameof(MyClass.Property));
dict.Add(propertyInfo, Activator.CreateInstance(typeof(List<>).MakeGenericType(propertyInfo.PropertyType)));
dict[propertyInfo].GetType() is List<int>, but you're not going to get Intellisense with it as it is dynamic.
Currently I am doing something along the lines of:
public class UselessClass
{
public string x;
public int y;
}
I only ever use this class once in a function...
Dictionary<string, UselessClass> dict;
I'd like to be able to edit the values of the UselessClass, so I believe a Tuple isn't sufficient as they are read-only once created. I'd also like to have the named variables x and y to do things like:
dict["hello"].y++;
Can I do this without having to have this UselessClass sitting around the code when really it's only ever used once for a function? Some sort of anonymous class with named variables?
To add more details:
This is purely used in an algorithmic function where I want to adjoin a string with certain variables, namely another string x and an integer representing a distance
The best way I can think of adding properties to an already existing class like string is by using a dictionary.
Rather than doing:
Dictionary<string, string> names;
Dictionary<string, int> distances;
which seems like a waste of memory, I'd rather get both names and distances in the same structure.
But the structure itself is meaningless on its own, it's only used in the algorithm to perform a calculation.
No - anonymous types are immutable. If you want a mutable type use a class (not a struct). Using dynamic and ExpandoObject would be one alternative but you lose design-time type safety.
If you give some more context as how they are used there may be other alternatives.
To provide a similar solution as terrybozzio, albeit a less hackish one (using a single-element array isn’t exactly that nice), you could also use a wrapper that makes a type mutable:
class Mutable<T>
{
public Mutable(T value)
{
Value = value;
}
public T Value { get; set; }
}
You could then even use this for anonymous types:
var x = new {
Foo = "Bar",
Baz = new Mutable<int>(2)
};
Console.WriteLine(x.Baz.Value); // 2
x.Baz.Value++;
Console.WriteLine(x.Baz.Value); // 3
But as I said in a comment above, you can’t really use an anonymous type if you need to reference the type in the dictionary declaration. You could use a tuple, but overall, you gain a lot more flexibility if you just introduce a custom type. For example if you decide that you need another value in there (for whatever reason), then you can simply add it without everything breaking. If you on the other hand use a tuple or something similar, you would have to update every single use of it.
One possibility is like you said using Tuple but since their elements cannot be changed you can do a little "hack" if you wanna call it is to declare an Tuple<int[],string[]> so when you add an item to the dictionary you instantiate the tuple but with only 1 element in each array which can be manipulated:
Dictionary<string,Tuple<int[],string[]>> test = new Dictionary<string, Tuple<int[],string[]>>();
//here i add a new dict entry and to the int[] i assign the value 5.
test.Add("test1", new Tuple<int[], string[]>(new int[1]{5}, new string[1]));
test["test1"].Item1[0]++;
test["test1"].Item1[0]++;
//here the int will be 7.
Although i would go with the UselessClass...
Is there any way to retrieve a key from a SortedDictionary that is equal to a given object? To illustrate, lets say I create a dictionary that has a fairly memory-heavy, immutable key type:
var dictionary = SortedDictionary<MyHugeType, int>();
var myEnormousKey = new MyHugeType();
dictionary[myEnormousKey] = 123;
Then later on, I do something like this:
// This is a new instance, but it's identical to the previous key
var myIdenticalKey = new MyHugeType();
if(dictionary.ContainsKey(myIdenticalKey)) {
myIdenticalKey = dictionary.GetKeyEqualTo(myIdenticalKey);
}
// Use myIdenticalKey reference...
Obviously, SortedDictionary does not have a "GetKeyEqualTo" method. But is there some way I could achieve a similar effect? This would basically have the effect of intern-ing the heavy key objects so that identical instances could be discarded. I know I can do this using the SortedList class by retrieving the key's index and subsequently its matching object instance, but SortedDictionary's consistent insertion performance would be better for my uses.
Short of iterating through all the dictionary's keys to search for a match, or writing my own BST class, is there any way to achieve this end with .NET's built in collections?
You could change your value object from int to a struct or class containing both the value and the original key. Then to access the original key you can do:
dictionary[myIdenticalKey].OriginalKey
and for the value something like:
dictionary[myIdenticalKey].Value
If you override Equals() and GetHashCode() in MyHugeType with code that determines if two instances are the same, then you won't get duplicate keys in the dictionary. Is this what you mean?
You could implement the IEquatable interface in your key class. There you specify when two objects of the class are equal to each other. After that you simply test the existence of an entry using ContainsKey and when that returns true you can obtain it using the [] operator.
You could also provide a IComparer implementation to achieve the same result.
Id' like to create a list of data that will be passed from method to method, however I can't use a struct because the data that will be contained in this list will vary depending on the input.
For example
if (x == 1) {
a = 1
b = true
c = 42
d = "hello"
}
if (x == 2) {
a = 2
b = 'g'
c = "sup"
}
I believe my options are thus:
Create an array or List of strings, and cast the data back to what it originally was from strings. This is messy and could lead to bugs of uninterpretable input, though wouldn't be so bad since it'd all be detected at runtime.
Create a struct for each possibility - Is this even good practice?
Somehow use generics. From what I know, while generics are type-safe yet not type-strict, they must be cast to types before being used. Eg if I wanted a List of items here, I'd need to cast them to strings much like would happen with solution 1, making this useless.
My question then, is which of these options is the best? Or is there an alternate option using some sort of generic type I don't know about? The number of possible variables in each case may change, as with their types. I'd like to be able to return a single List or Array to the calling method, so that it may appropriately deal with the result. It will know how to deal with each group of data based on the value of a, as it will be the 'action choice' identifier. I'm also aware that casting them to objects and back each time is very intensive so I'd rather avoid that.
This is probably pretty simple but it has me stumped...
Since you don't know before hand what the list will contain, it looks like a good case for using an ArrayList.
If you want to get back to the values using a key, consider using a Hashtable.
The general principal in .NET is that every type can be cast to System.Object (although it may involve boxing). You can use a method like
void Foo(params object[] parameters) { ... }
Or use the System.Collections.ArrayList class.
The 'problem' is that when you want to use such a value, you will need code like:
if (parameters[i] is string)
{
string s = (string) parameters[i];
...
}
Sorry, this is not a code related answer: there may be a faulty design hidden behind such a construct. Make sure you know what you are doing, otherwise things might fire back.
If not knowing the type of the fields you use beforehand really is required, this calls for an approach that saves the data with their type, like
struct foo {
private object _value;
private string _type;
foo(string myType, object myValue) {
_value = myValue;
_type = myType;
}
}
and then using Generics to handle the business logic.
Basically you need a list typed to Object, and then yes, you're in a mode of casting back.
My question is, structurally, how will you know what indexes are of which type? This sounds like a painful solution at best.
If you really need to store differing types in the list, perhaps try a struct which contains a member of each type, as well as a flag indicating which data type is represented. Then use a generic collection for that struct. Something like (off the top of my head)
struct FooType
{
public string StringValue;
public bool BoolValue;
public int IntValue;
public char CharValue;
public string DataType;
// You'd probably want constructors too
}
Then the generic list:
var values = new List<FooType>();
Now you can add and remove entries in the list using that type, which would then indicate what the core data really is.
I still don't like the answer; it sounds like your design may be trying to do too much and there may be refactoring opportunities, but since I don't see much more of your code or intent, all I can do is answer what you've asked. :)
You could represent the data items using a Dictionary/Hashtable and then add these dictionaries to a List.
You could also add extra type information into the dictionary value if needed.