Can I Create a Dictionary of Generic Types?
EDIT: Now I've reread the question...
You can't do this, but a custom collection would handle it to some extent. You'd basically have a generic Add
method:
public void Add<T>(string key, List<T> list)
(The collection itself wouldn't be generic - unless you wanted to make the key type generic.)
You couldn't extract values from it in a strongly typed manner though, because the compiler won't know which type you've used for a particular key. If you make the key the type itself, you end with a slightly better situation, but one which still isn't supported by the existing collections. That's the situation my original answer was responding to.
EDIT: Original answer, when I hadn't quite read the question correctly, but which may be informative anyway...
No, you can't make one type argument depend on another, I'm afraid. It's just one of the things one might want to express in a generic type system but which .NET's constraints don't allow for. There are always going to be such problems, and the .NET designers chose to keep generics relatively simple.
However, you can write a collection to enforce it fairly easily. I have an example in a blog post which only keeps a single value, but it would be easy to extend that to use a list.
Creating Dictionaries of generic types
I think you just have to cast it using Cast<T>
.
return _fruits[typeof(T)].Values.Cast<T>();
Using a (IEnumerable<T>)
to cast does not work because it will cast the whole thing. You may know this already: List<object>
can't be casted to List<int>
. The same phenomenon happens here.
Therefore, we should use Cast<T>
. This method will cast each element of the enumerable to the specified type, and returning the resulting enumerable.
C# Dictionary of generic classes
I tried using boxing/unboxing and came up with this solution. It appears to work... so far. But it doesn't seem very safe.
public interface Variable
{
object getValue();
void setValue(object value);
Type myType();
}
public class Variable<T>: Variable
{
private T myValue;
public object getValue()
{
return myValue;
}
public void setValue(object value)
{
myValue = (T)value;
}
public Type myType() { return myValue.GetType(); }
}
Dictionary<string, Variable> vars = new Dictionary<string, Variable>();
Variable<int> age = new Variable<int>();
age.setValue(21);
vars.Add("age", age);
Variable theAgeVar;
vars.TryGetValue("age", out theAgeVar);
Console.WriteLine("age = " + theAgeVar.getValue());
Variable<double> height = new Variable<double>();
height.setValue(5.9);
Variable theHeightVar;
vars.TryGetValue("age", out theHeightVar);
Debug.Log("height = " + theHeightVar.getValue());
This prints:
age = 21
height = 5.9
One thing I do not like is that I had to make the return type of getValue()
be an object
. If I wanted myValue
(which is of type T
) to implement IComparable
, for instance, then this information is lost when the boxing happens and the caller receives an object
.
Dictionary of generic lists or varying types
How about Dictionary<string, dynamic>
assuming you're on C# 4
Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Dict.Add("int", new List<int>());
Dict.Add("string", new List<string>());
Dict["int"].Add(12);
Dict["string"].Add("str");
foreach (KeyValuePair<string, dynamic> pair in Dict) {
Type T = pair.Value.GetType();
Console.WriteLine(T.GetGenericArguments()[0].ToString());
}
That prints out
System.Int32
System.String
Is that what you're looking for?
C# - Define a dictionary of generic functions
Try this class:
public class Stringifier
{
private Dictionary<Type, Delegate> _store
= new Dictionary<Type, Delegate>();
public void Store<T>(Func<T, string> value)
{
_store[typeof(T)] = value;
}
public Func<T, string> Fetch<T>()
{
return (Func<T, string>)_store[typeof(T)];
}
public string Fetch<T>(T value)
{
return this.Fetch<T>().Invoke(value);
}
public string Fetch(Type type, object value)
{
return (string)
(
typeof(Stringifier)
.GetMethods()
.Where(x => x.Name == "Fetch")
.Where(x => x.IsGenericMethod)
.Where(x => x.ReturnType == typeof(string))
.Select(x => x.MakeGenericMethod(type))
.First()
.Invoke(this, new [] { value })
);
}
}
Then you can do this:
var stringifier = new Stringifier();
stringifier.Store<string>(s => $"!{s}!");
stringifier.Store<float>(f => f.ToString());
stringifier.Store<bool>(b => b.ToString());
var bar = "XXX";
var value = stringifier.Fetch(bar.GetType(), bar);
Console.WriteLine(value);
The output I get is !XXX!
.
Generic type struct in dictionary
If you want your dictionary to be type specific:
private Dictionary<string, Command<my_type>> _commandMap;
If you want everything in one dictionary, then don't use a generic for the class.
You wrote, that you want to store a class type property to instantiate it later. Yet in your code you store a class instance, not a class type.
I think this is what you are looking for:
internal struct Command
{
internal string trigger;
internal Type clazz;
internal string category;
}
or
internal struct Command
{
internal string trigger;
internal IMyInterface clazz;
internal string category;
}
and finally:
private Dictionary<string, Command> _commandMap;
Infer Generic type in dictionary property
The type you're looking for is a dictionary where each entry is some IMyInterface<T>
type, but not any particular T
. This is probably best expressed as an existential type like (possibly) {[k: string]: IMyInterface<exists T>}
, which isn't currently supported natively in TypeScript (nor most other languages with generics). TypeScript (and most other languages with generics) only has universal types: someone who wants a value of type X<T>
can specify any type for T
that they want, and the provider of the value must be able to comply. An existential type is the opposite: someone who wants to provide a value of a type like X<exists T>
can choose any specific type for T
that they want, and the receiver of that value just has to comply. Existential types let you "hide" the generic type inside a non-generic type.
But, TypeScript doesn't have existential types, so we'll have to do something else. (Well, it doesn't have native existential types. You can emulate them by using generic functions and inverting control via callbacks, but that's even more complicated to use than the solution I'm going to suggest next. If you're still interested in existentials you can read the linked article about it)
The next best thing we can do is to describe the shape of IMyDictionary
as a generic type, where we don't really care about it, and get the compiler to infer it for us as much as possible. Here's one way:
type IMyDictionary<T> = { [K in keyof T]: IMyInterface<T[K]> }
const asIMyDictionary = <T>(d: IMyDictionary<T>) => d;
The idea is that instead of declaring a variable to be of type IMyDictionary
, you use the helper function asIMyDictionary()
to take the value and produce a suitable type IMyDictionary<T>
. This only works, by the way, because the type IMyDictionary<T>
is a homomorphic mapped type, so T
can be inferred from a value of type IMyDictionary<T>
. Let's see it in action:
const myDictionary = asIMyDictionary({
test1: {
propA: { name: "John", age: 18 },
propB: { age: 40 }
},
test2: {
propA: { size: 10, color: "blue" },
propB: { color: "purple" }
},
test3: {
propA: { problem: true },
propB: { oops: false } // error!
// ~~~~~~~~~~~~
// 'oops' does not exist in type '{ problem?: boolean | undefined; }'
}
});
This works and gives you errors where you expect them. Yay!
The caveat here is you still have to drag around this T
type you don't care about. Any function or type which you were hoping would just deal with a concrete IMyDictionary
will have to become generic. Maybe that's not too painful to you. If it is, you can think about the "emulated" existential type. But I've already written a lot here, so hopefully the above will help you... if you need me to write out the emulated existential version, I can.
Good luck!
Create a dictionary of generic variables in swift
variable1
and variable2
are not of type Entity
but are in fact Entity<Float>
and Entity<String>
which are two unrelated types. Use a protocol
to unite them:
protocol EntityProtocol { }
class Entity<T> : EntityProtocol {
var _value: T
var value: T { get { return _value } set {_value = newValue}}
init (defaultValue: T) {
_value = defaultValue
}
}
class FloatEntity: Entity<Float> {
}
class StringEntity: Entity<String> {
}
func run () {
let variable1: Entity = FloatEntity (defaultValue: 1)
let variable2: Entity = StringEntity (defaultValue: "")
var dictionary: Dictionary<String, EntityProtocol> = [
"One": FloatEntity (defaultValue: 1),
"Two": StringEntity (defaultValue: ""),
]
print (variable1)
print (variable2)
print (dictionary)
}
Related Topics
How to Asynchronously Read the Standard Output Stream and Standard Error Stream at Once
Monitor a Process's Network Usage
ASP.NET Button Onclick Event Not Firing
"Not In" Clause in Linq to Entities
How to Retrieve the Screen Resolution from a C# Winform App
How to Have a Loop in a Windows Service Without Using the Timer
How to Add Option Groups in ASP.NET Drop Down List
How to Dispose of a Backgroundworker
Using a List as a Data Source for Datagridview
Programmatic Way to Get All the Available Languages (In Satellite Assemblies)
Why Is Parallel.Foreach Much Faster Then Asparallel().Forall() Even Though Msdn Suggests Otherwise
Select Either a File or Folder from the Same Dialog in .Net
Reasons for Why a Winforms Label Does Not Want to Be Transparent