If it exists, what is the C# equivalent of the following Java code:
new HashMap<Class<? extends BaseClass>, Integer>();
I currently use new Dictionary<Type, int>(), which is more like new HashMap<Class<?>, Integer>() which is obviously not the same.
(Ignore the differences between HashMap and Dictionary)
Edit: To clarify, I am not trying to define a new class, simply create an instance of HashMap/Dictionary.
There is no equivalent of the Java wildcard in C#. In Java, the type for types is Class<T> where T is the class itself. The equivalent in C# is the type Type, which is not generic. So it seems that the best you can do is to have, as you said, a Dictionary<Type, int>, and if it's encapsulated in a class you can restrict what you put in the dictionary in the code (so it will just be a runtime check):
private Dictionary<Type, int> myDictionary = new Dictionary<Type, int>();
public void Add(Type type, int number) {
if (!typeof(BaseClass).IsAssignableFrom(type)) throw new Exception();
myDictionary.Add(type, number);
}
You can even implement your own IDictionary with that logic.
UPDATE
Another runtime trick I can think of is to use a wrapper class for your types:
public class TypeWrapper<T>
{
public Type Type { get; private set; }
public TypeWrapper(Type t)
{
if (!typeof(T).IsAssignableFrom(t)) throw new Exception();
Type = t;
}
public static implicit operator TypeWrapper<T>(Type t) {
return new TypeWrapper<T>(t);
}
}
(Also implement Equals and GetHashCode, just delegate to Type.)
And then your dictionary becomes:
var d = new Dictionary<TypeWrapper<BaseClass>, int>();
d.Add(typeof(BaseClass), 2);
d.Add(typeof(Child), 3);
I believe you want to constrain type parameters to generic types - the where keyword is used for that:
class MyDict<TKey, TValue> : Dictionary<TKey, TValue> where TValue : SomeBaseClass
{
...
}
Is this what you're asking for or am I misunderstanding your question?
Edit: you cannot do exactly what you ask for in C# - you can't define an local instance of a generic type with a type constraint. You can, however, pre-declare your constrained Dictionary type (like my example) and then create an instance of that type like so:
// SomeClass will have to inherit from SomeBaseClass
MyDict<SomeClass> instance = new MyDict<SomeClass> ();
I think this is close to what you're looking for. Post a comment if I misunderstand it - I don't know Java this deep.
Was looking into this same problem and this poor man's checker is the best thing I could come up with:
class MyValue {
public Type Type { get; private set; }
private MyValue(Type type)
{
this.Type = type;
}
public MyValue of<T>() where T : BaseClass
{
return new MyValue(typeof(T));
}
}
IDictionary<int, MyValue> myDictionary = new Dictionary<int, MyValue>()
{
{ 1, MyValue.of<SubClass1>(); },
{ 2, MyValue.of<SubClass2>(); },
{ 3, MyValue.of<NotSubClass>(); }, // this causes a compile error
};
Related
I'd like to create a Dictionary object, with string Keys, holding values which are of a generic type. I imagine that it would look something like this:
Dictionary<string, List<T>> d = new Dictionary<string, List<T>>();
And enable me to add the following:
d.Add("Numbers", new List<int>());
d.Add("Letters", new List<string>());
I know that I can do it for a list of strings, for example, using this syntax:
Dictionary<string, List<string>> d = new Dictionary<string, List<string>>();
d.Add("Key", new List<string>());
but I'd like to do it for a generic list if possible...
2 questions then:
Is it possible?
What's the syntax?
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.
Would something like this work?
public class GenericDictionary
{
private Dictionary<string, object> _dict = new Dictionary<string, object>();
public void Add<T>(string key, T value) where T : class
{
_dict.Add(key, value);
}
public T GetValue<T>(string key) where T : class
{
return _dict[key] as T;
}
}
Basically it wraps all the casting behind the scenes for you.
How about Dictionary<string, dynamic>? (assuming you're on C# 4)
Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Source: https://stackoverflow.com/a/5038029/3270733
I prefer this way of putting generic types into a collection:
interface IList
{
void Add (object item);
}
class MyList<T> : List<T>, IList
{
public void Add (object item)
{
base.Add ((T) item); // could put a type check here
}
}
class Program
{
static void Main (string [] args)
{
SortedDictionary<int, IList>
dict = new SortedDictionary<int, IList> ();
dict [0] = new MyList<int> ();
dict [1] = new MyList<float> ();
dict [0].Add (42);
dict [1].Add ("Hello"); // Fails! Type cast exception.
}
}
But you do lose the type checks at compile time.
I came to a type safe implementation using ConditionalWeakTable.
public class FieldByType
{
static class Storage<T>
where T : class
{
static readonly ConditionalWeakTable<FieldByType, T> table = new ConditionalWeakTable<FieldByType, T>();
public static T GetValue(FieldByType fieldByType)
{
table.TryGetValue(fieldByType, out var result);
return result;
}
public static void SetValue(FieldByType fieldByType, T value)
{
table.Remove(fieldByType);
table.Add(fieldByType, value);
}
}
public T GetValue<T>()
where T : class
{
return Storage<T>.GetValue(this);
}
public void SetValue<T>(T value)
where T : class
{
Storage<T>.SetValue(this, value);
}
}
It can be used like this:
/// <summary>
/// This class can be used when cloning multiple related objects to store cloned/original object relationship.
/// </summary>
public class CloningContext
{
readonly FieldByType dictionaries = new FieldByType();
public void RegisterClone<T>(T original, T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
dictionary = new Dictionary<T, T>();
dictionaries.SetValue(dictionary);
}
dictionary[original] = clone;
}
public bool TryGetClone<T>(T original, out T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
clone = default(T);
return false;
}
return dictionary.TryGetValue(original, out clone);
}
}
See also this question where the type of the values is stored in as a generic parameter of the keys.
We're using lots of reflection to create an extensible administration tool. We needed a way to register items in the global search in the module definition. Each search would return results in a consistent way, but each one had different dependencies. Here's an example of us registering search for a single module:
public void ConfigureSearch(ISearchConfiguration config)
{
config.AddGlobalSearchCallback<IEmploymentDataContext>((query, ctx) =>
{
return ctx.Positions.Where(p => p.Name.Contains(query)).ToList().Select(p =>
new SearchResult("Positions", p.Name, p.ThumbnailUrl,
new UrlContext("edit", "position", new RouteValueDictionary(new { Id = p.Id }))
));
});
}
In the background during module registration, we iterate over every module and add the Func to a SearchTable with an instance of:
public class GenericFuncCollection : IEnumerable<Tuple<Type, Type, Object>>
{
private List<Tuple<Type, Type, Object>> objects = new List<Tuple<Type, Type, Object>>();
/// <summary>
/// Stores a list of Func of T where T is unknown at compile time.
/// </summary>
/// <typeparam name="T1">Type of T</typeparam>
/// <typeparam name="T2">Type of the Func</typeparam>
/// <param name="func">Instance of the Func</param>
public void Add<T1, T2>(Object func)
{
objects.Add(new Tuple<Type, Type, Object>(typeof(T1), typeof(T2), func));
}
public IEnumerator<Tuple<Type, Type, object>> GetEnumerator()
{
return objects.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return objects.GetEnumerator();
}
}
Then when we finally call it, we do it with reflection:
var dependency = DependencyResolver.Current.GetService(search.Item1);
var methodInfo = search.Item2.GetMethod("Invoke");
return (IEnumerable<SearchResult>)methodInfo.Invoke(search.Item3, new Object[] { query, dependency });
I didn't find what I was looking for here but after reading I think it might be what is being asked for so an attempt to answer.
The problem is that when you use Dictionary it is a closed constructed type and all elements must be of the TValue type. I see this question in a number of places without a good answer.
Fact is that I want indexing but each element to have a different type and based on the value of TKey we already know the type. Not trying to get around the boxing but trying to simply get more elegant access something like DataSetExtensions Field. And don't want to use dynamic because the types are known and it is just not wanted.
A solution can be to create a non generic type that does not expose T at the class level and therefore cause the TValue part of the dictionary to be closed constructed. Then sprinkle in a fluent method to help initialization.
public class GenericObject
{
private object value;
public T GetValue<T>()
{
return (T)value;
}
public void SetValue<T>(T value)
{
this.value = value;
}
public GenericObject WithValue<T>(T value)
{
this.value = value;
return this;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, GenericObject> dict = new Dictionary<string, GenericObject>();
dict["mystring"] = new GenericObject().WithValue<string>("Hello World");
dict["myint"] = new GenericObject().WithValue<int>(1);
int i = dict["myint"].GetValue<int>();
string s = dict["mystring"].GetValue<string>();
}
}
Other posibility it's to use the variable dynamic.
For example:
Dictionary<string, List<dynamic>> d = new Dictionary<string, List<dynamic>>();
d.Add("Key", new List<dynamic>());
the variable dynamic resolve the type on runtime.
No, but you can use object instead of generic type.
Long answer:
The current version of C# will not allow you to make entries of generic type in a dictionary. Your options are either a) create a custom class that is the same as a dictionary except allow it to accept generic types, or b) make your Dictionary take values of type object. I find option b to be the simpler approach.
If you send lists of specific types, then when you go to process the lists you will have to test to see what kind of list it is. A better approach is to create lists of objects; this way you can enter integers, strings, or whatever data type you want and you don't necessarily have to test to see what type of object the List holds. This would (presumably) produce the effect you're looking for.
Here is a short console program that does the trick:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dictionary
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var lstIntList = new List<object>();
var lstStrings = new List<object>();
var lstObjects = new List<object>();
string s = "";
lstIntList.Add(1);
lstIntList.Add(2);
lstIntList.Add(3);
lstStrings.Add("a");
lstStrings.Add("b");
lstStrings.Add("c");
dic.Add("Numbers", lstIntList);
dic.Add("Letters", lstStrings);
foreach (KeyValuePair<string, object> kvp in dic)
{
Console.WriteLine("{0}", kvp.Key);
lstObjects = ((IEnumerable)kvp.Value).Cast<object>().ToList();
foreach (var obj in lstObjects)
{s = obj.ToString(); Console.WriteLine(s);}
Console.WriteLine("");
}
Console.WriteLine("");
Console.WriteLine("press any key to exit");
Console.ReadKey();
}//end main
}
}
One of the way is to create a Dictionary value with type "object" like:
Dictionary<string, object> d = new Dictionary<string, object>();
So, here object datatype is used as a generic datatype, you can put anything in this as a value.
Or it's possible to use generic Type like this
public static void SafeUpdateInDictionary<T, L>(T DictionaryToBeUpdated, string Key, L Value) where T : Dictionary<string, L>
{
if (DictionaryToBeUpdated != null)
{
if(Value != null)
{
if (!DictionaryToBeUpdated.ContainsKey(Key))
DictionaryToBeUpdated.Add(Key, Value);
else
DictionaryToBeUpdated[Key] = Value;
}
}
}
I didn't know how to express it clearly.
I have this interface:
interface IConverter
{
Dictionary<Type, Func<string, object>> ConversionMethods { get; }
}
Basically, it defines a contract saying that a class implementing it should provide conversion methods for all the custom types it uses (be them enums or anything).
Is it possible to replace object in Func's generic types with its corresponding dictionary key's type (so it is impossible to have two unmatching types)?
I think it's not possible, but the alternatives are a bit annoying (using dynamic or object, creating a specialized dictionary...).
edit 1: Imaginary exemple of use
interface IConverter
{
Dictionary<Type, Func<string, object>> GetConversionMethods();
}
enum A
{
AA,AB,AC
}
enum B
{
BA, BB, BC
}
class blah : IConverter
{
public Dictionary<Type, Func<string, object>> GetConversionMethods()
{
var d = new Dictionary<Type, Func<string, object>>
{
{
typeof(A),
(s) =>
{
// here, I could return whatever I want because the 'Func' returns 'object'
return s == "AA" ? A.AA : s == "AB" ? A.AB : A.AC;
}
},
{
typeof(B),
(s) =>
{
// same
return s == "BA" ? B.BA : s == "BB" ? B.BB : B.BC;
}
}
};
return d;
}
void blahah()
{
// and here, I also get an `object`, where I would like to have a A
GetConversionMethods()[typeof(A)]("123");
}
}
This gets a bit complex, but it works.
First, you'll need to encapsulate the conversion Funcs inside classes, so that you can handle them more easily and without exposing all their differing type arguments. Then you'll need to define interfaces or base classes to hide the various generic arguments from places they'll cause problems, and allow you to put different converters in the same collection. Then, you'll need ways for the various converters to signal what types they work with without using those type arguments directly. Then you just need to wrap it all in a class with a method that'll find you the right converter on demand.
I'll walk you through it.
First, this base class will be our way to handle a converter without worrying about its generic type arguments, but still know what types it work with.
public abstract class OneWayTypeConverterBase : IConvertFromType, IConvertToType
{
public abstract Type AcceptsType { get; }
public abstract Type ReturnsType { get; }
}
Now we inherit from that base class. This is the class that does the actual work of converting; you can instantiate it with a lambda that does whatever conversion operation you need. Notice that it implements the properties we defined above.
public class OneWayTypeConverter<TSource, TTarget> : OneWayTypeConverterBase
{
public OneWayTypeConverter(Func<TSource, TTarget> conversionMethod)
{
_conversionMethod = conversionMethod;
}
public override Type AcceptsType => typeof(TSource);
public override Type ReturnsType => typeof(TTarget);
private readonly Func<TSource, TTarget> _conversionMethod;
public TTarget Convert(TSource sourceObject)
{
return _conversionMethod(sourceObject);
}
}
Now we need a single place to hold all of this, so that consuming code has an entry point. For simplicity, I had it take in a flat collection of converters, and then file them all into nested dictionaries so that it can do the lookups later without having to call typeof all the time.
public class TypeConverter
{
public TypeConverter(IEnumerable<OneWayTypeConverterBase> converters)
{
_converters = converters
.GroupBy(x => x.AcceptsType)
.ToDictionary(
kSource => kSource.Key,
vSource => vSource
.ToDictionary(kTarget => kTarget.ReturnsType, vTarget => vTarget));
}
private Dictionary<Type, Dictionary<Type, OneWayTypeConverterBase>> _converters;
public TTarget ConvertType<TSource, TTarget>(TSource sourceObject)
{
Dictionary<Type, OneWayTypeConverterBase> baseConverters;
if (_converters.TryGetValue(sourceObject.GetType(), out baseConverters))
{
OneWayTypeConverterBase baseConverter;
if (baseConverters.TryGetValue(typeof(TTarget), out baseConverter))
{
OneWayTypeConverter<TSource, TTarget> converter = baseConverter as OneWayTypeConverter<TSource, TTarget>;
if (converter != null)
{
return converter.Convert(sourceObject);
}
}
throw new InvalidOperationException("No converter found for that target type");
}
else
{
throw new InvalidOperationException("No converters found for that source type");
}
}
}
So now, you can set it up like this:
var converter = new TypeConverter(new List<OneWayTypeConverterBase>
{
new OneWayTypeConverter<int, string>(x => $"The number was {x}"),
new OneWayTypeConverter<int, bool>(x => x != 0),
new OneWayTypeConverter<bool, string>(x => $"The bool was {x}")
});
and then whenever you need it, you can just use it like this:
var result = converter.ConvertType<int, string>(4);
It depends in how far you can change the signatures, but at the least the interface can enforce using a generic type. How the converters are added strongly typed is then the responsibility of the implementer and never of the caller.
The implementation itself can use any construction to provide the converter. Event if...else, but to use a dictionary under the hood, a dictionary of the type Dictionary<Type, Delegate> can be used, where the converters can be added strongly typed. The example below uses a helper set<T> function to ensure the dictionary is set in the expected manner.
interface IConverter
{
Func<string,T> GetConverter<T>(); //the method returned is always strongly typed, so the caller is never responsible for type checking
}
enum A{AA,AB,AC}
enum B{BA, BB, BC}
class blah : IConverter
{
public Func<string,T> GetConverter<T>()
{
if(methods.TryGetValue(typeof(T), out var fn)) //side note, out var fn will not work in older visual studio versions. In that case declare fn before this line
return (Func<string,T>)fn; //the set<T> method ensures that this conversion is safe
throw new NotImplementedException();
}
public blah()
{
set<A>(s => s == "AA" ? A.AA : s == "AB" ? A.AB : A.AC); //copied from the example. Enum.Parse could perhaps be used instead
set<B>(s => s == "BA" ? B.BA : s == "BB" ? B.BB : B.BC);
}
Dictionary<Type, Delegate> methods= new Dictionary<Type, Delegate>(); // Delegate can be used as a type to handle all lambda's. It's the implementers responsibility to handle with care. Something like the set<T> helper method is recommended
void set<T>(Func<string,T> fn) //helper method to assign the strongly typed methods to the specific type
{
methods[typeof(T)] = fn;
}
}
static void blahah()
{
new blah().GetConverter<A>()("123");
}
I've got a Dictionary<Type, HashSet<GenericType>> which I use to hold my data in, and I am trying to make a function that returns one of those HashSets given the generic type T : GenericType.
Basically
Dictionary<Type, HashSet<GenericType>> data;
public HashSet<T> Get<T>() where T : GenericType
{
var tp = typeof(T);
//....check if its in the dictionary, fill if not....
return data[tp];
}
This isn't valid of course. But I am having a very hard time figuring out what I should do instead.
I feel like returning T is optimal though, since you then can do something like this:
Get<Derived>().Where(x => x.DerivedProperty == someValue)
But the only thing I thought of was to create a new HashSet<T> every time Get is called, and then using a foreach-loop cast and add every item from the already existing HashSet in the Dictionary, but this feels like such a waste?
Another idea is to skip HashSet and use another (covariant?) collection. But since these collections will hold lots of data, maybe it isn't the best idea either.
So in short I am wondering what the best approach for this problem is.
Update
So this is the structure I got. The type which contains data is a type of service in my code structure. It will via reflection be loaded and initialized at runtime. From there I later use a ServiceFactory of sorts to get that service.
public class foo : Service
{
public Dictionary<Type, HashSet<BaseClass>> data = new Dictionary<Type, HashSet<BaseClass>>();
public T Get<T>() where T : BaseClass
{
var tp = typeof(T);
if (!data.ContainsKey(tp))
{
data.Add(typeof(Derived), new HashSet<BaseClass>() { new Derived(), new Derived(), new Derived() });
}
return data[tp];//this wont compile.
}
}
public class Derived : BaseClass
{
public int ExampleVariable {get;set;}
}
public abstract class BaseClass
{
// some things in here.
public void DoCommonStuff()
{
}
}
class program
{
static void Main(string[] args)
{
var service = ServiceFactory.GetService<foo>();
var collection = service.Get<Derived>();
}
}
I would just change the type of the dictionary, and cast inside your Get method. Definitely, definitely make your dictionary private though - then you can make sure that only your code (ideally only the Get method) can access it:
// Any data[typeof(Foo)] value will be a HashSet<Foo>. Only
// the Get method should access this dictionary.
private readonly Dictionary<Type, object> data = new Dictionary<Type, object>();
public HashSet<T> Get<T>() where T : GenericType
{
var tp = typeof(T);
object value;
if (data.TryGetValue(tp, out value))
{
return (HashSet<T>) value;
}
var newSet = new HashSet<T>()
// Populate newSet here
data[tp] = newSet;
return newSet;
}
I have a bit more discussion of a closely-related issue in a blog post.
I'd like to create a Dictionary object, with string Keys, holding values which are of a generic type. I imagine that it would look something like this:
Dictionary<string, List<T>> d = new Dictionary<string, List<T>>();
And enable me to add the following:
d.Add("Numbers", new List<int>());
d.Add("Letters", new List<string>());
I know that I can do it for a list of strings, for example, using this syntax:
Dictionary<string, List<string>> d = new Dictionary<string, List<string>>();
d.Add("Key", new List<string>());
but I'd like to do it for a generic list if possible...
2 questions then:
Is it possible?
What's the syntax?
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.
Would something like this work?
public class GenericDictionary
{
private Dictionary<string, object> _dict = new Dictionary<string, object>();
public void Add<T>(string key, T value) where T : class
{
_dict.Add(key, value);
}
public T GetValue<T>(string key) where T : class
{
return _dict[key] as T;
}
}
Basically it wraps all the casting behind the scenes for you.
How about Dictionary<string, dynamic>? (assuming you're on C# 4)
Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Source: https://stackoverflow.com/a/5038029/3270733
I prefer this way of putting generic types into a collection:
interface IList
{
void Add (object item);
}
class MyList<T> : List<T>, IList
{
public void Add (object item)
{
base.Add ((T) item); // could put a type check here
}
}
class Program
{
static void Main (string [] args)
{
SortedDictionary<int, IList>
dict = new SortedDictionary<int, IList> ();
dict [0] = new MyList<int> ();
dict [1] = new MyList<float> ();
dict [0].Add (42);
dict [1].Add ("Hello"); // Fails! Type cast exception.
}
}
But you do lose the type checks at compile time.
I came to a type safe implementation using ConditionalWeakTable.
public class FieldByType
{
static class Storage<T>
where T : class
{
static readonly ConditionalWeakTable<FieldByType, T> table = new ConditionalWeakTable<FieldByType, T>();
public static T GetValue(FieldByType fieldByType)
{
table.TryGetValue(fieldByType, out var result);
return result;
}
public static void SetValue(FieldByType fieldByType, T value)
{
table.Remove(fieldByType);
table.Add(fieldByType, value);
}
}
public T GetValue<T>()
where T : class
{
return Storage<T>.GetValue(this);
}
public void SetValue<T>(T value)
where T : class
{
Storage<T>.SetValue(this, value);
}
}
It can be used like this:
/// <summary>
/// This class can be used when cloning multiple related objects to store cloned/original object relationship.
/// </summary>
public class CloningContext
{
readonly FieldByType dictionaries = new FieldByType();
public void RegisterClone<T>(T original, T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
dictionary = new Dictionary<T, T>();
dictionaries.SetValue(dictionary);
}
dictionary[original] = clone;
}
public bool TryGetClone<T>(T original, out T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
clone = default(T);
return false;
}
return dictionary.TryGetValue(original, out clone);
}
}
See also this question where the type of the values is stored in as a generic parameter of the keys.
We're using lots of reflection to create an extensible administration tool. We needed a way to register items in the global search in the module definition. Each search would return results in a consistent way, but each one had different dependencies. Here's an example of us registering search for a single module:
public void ConfigureSearch(ISearchConfiguration config)
{
config.AddGlobalSearchCallback<IEmploymentDataContext>((query, ctx) =>
{
return ctx.Positions.Where(p => p.Name.Contains(query)).ToList().Select(p =>
new SearchResult("Positions", p.Name, p.ThumbnailUrl,
new UrlContext("edit", "position", new RouteValueDictionary(new { Id = p.Id }))
));
});
}
In the background during module registration, we iterate over every module and add the Func to a SearchTable with an instance of:
public class GenericFuncCollection : IEnumerable<Tuple<Type, Type, Object>>
{
private List<Tuple<Type, Type, Object>> objects = new List<Tuple<Type, Type, Object>>();
/// <summary>
/// Stores a list of Func of T where T is unknown at compile time.
/// </summary>
/// <typeparam name="T1">Type of T</typeparam>
/// <typeparam name="T2">Type of the Func</typeparam>
/// <param name="func">Instance of the Func</param>
public void Add<T1, T2>(Object func)
{
objects.Add(new Tuple<Type, Type, Object>(typeof(T1), typeof(T2), func));
}
public IEnumerator<Tuple<Type, Type, object>> GetEnumerator()
{
return objects.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return objects.GetEnumerator();
}
}
Then when we finally call it, we do it with reflection:
var dependency = DependencyResolver.Current.GetService(search.Item1);
var methodInfo = search.Item2.GetMethod("Invoke");
return (IEnumerable<SearchResult>)methodInfo.Invoke(search.Item3, new Object[] { query, dependency });
I didn't find what I was looking for here but after reading I think it might be what is being asked for so an attempt to answer.
The problem is that when you use Dictionary it is a closed constructed type and all elements must be of the TValue type. I see this question in a number of places without a good answer.
Fact is that I want indexing but each element to have a different type and based on the value of TKey we already know the type. Not trying to get around the boxing but trying to simply get more elegant access something like DataSetExtensions Field. And don't want to use dynamic because the types are known and it is just not wanted.
A solution can be to create a non generic type that does not expose T at the class level and therefore cause the TValue part of the dictionary to be closed constructed. Then sprinkle in a fluent method to help initialization.
public class GenericObject
{
private object value;
public T GetValue<T>()
{
return (T)value;
}
public void SetValue<T>(T value)
{
this.value = value;
}
public GenericObject WithValue<T>(T value)
{
this.value = value;
return this;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, GenericObject> dict = new Dictionary<string, GenericObject>();
dict["mystring"] = new GenericObject().WithValue<string>("Hello World");
dict["myint"] = new GenericObject().WithValue<int>(1);
int i = dict["myint"].GetValue<int>();
string s = dict["mystring"].GetValue<string>();
}
}
Other posibility it's to use the variable dynamic.
For example:
Dictionary<string, List<dynamic>> d = new Dictionary<string, List<dynamic>>();
d.Add("Key", new List<dynamic>());
the variable dynamic resolve the type on runtime.
No, but you can use object instead of generic type.
Long answer:
The current version of C# will not allow you to make entries of generic type in a dictionary. Your options are either a) create a custom class that is the same as a dictionary except allow it to accept generic types, or b) make your Dictionary take values of type object. I find option b to be the simpler approach.
If you send lists of specific types, then when you go to process the lists you will have to test to see what kind of list it is. A better approach is to create lists of objects; this way you can enter integers, strings, or whatever data type you want and you don't necessarily have to test to see what type of object the List holds. This would (presumably) produce the effect you're looking for.
Here is a short console program that does the trick:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dictionary
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var lstIntList = new List<object>();
var lstStrings = new List<object>();
var lstObjects = new List<object>();
string s = "";
lstIntList.Add(1);
lstIntList.Add(2);
lstIntList.Add(3);
lstStrings.Add("a");
lstStrings.Add("b");
lstStrings.Add("c");
dic.Add("Numbers", lstIntList);
dic.Add("Letters", lstStrings);
foreach (KeyValuePair<string, object> kvp in dic)
{
Console.WriteLine("{0}", kvp.Key);
lstObjects = ((IEnumerable)kvp.Value).Cast<object>().ToList();
foreach (var obj in lstObjects)
{s = obj.ToString(); Console.WriteLine(s);}
Console.WriteLine("");
}
Console.WriteLine("");
Console.WriteLine("press any key to exit");
Console.ReadKey();
}//end main
}
}
One of the way is to create a Dictionary value with type "object" like:
Dictionary<string, object> d = new Dictionary<string, object>();
So, here object datatype is used as a generic datatype, you can put anything in this as a value.
Or it's possible to use generic Type like this
public static void SafeUpdateInDictionary<T, L>(T DictionaryToBeUpdated, string Key, L Value) where T : Dictionary<string, L>
{
if (DictionaryToBeUpdated != null)
{
if(Value != null)
{
if (!DictionaryToBeUpdated.ContainsKey(Key))
DictionaryToBeUpdated.Add(Key, Value);
else
DictionaryToBeUpdated[Key] = Value;
}
}
}
I have class where the relevant part looks like
class C {
void Method<T>(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
How should I define the list so that the class compiles?
I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)
I don't think you can do this in C#... you would have to add the type parameter to the class:
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<SomeClass<T>> list = new List<SomeClass<T>>();
}
The other option would be to use an interface:
class C {
void Method<T>(T obj)
where T : ISomeClass {
list.Add(obj);
}
List<ISomeClass> list = new List<ISomeClass>();
}
To do what you want, you have two options.
You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.
Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.
Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant.
You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature.
To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead.
If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.
I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.
class SomeClass<T>
{
}
class C
{
void Add<T>(SomeClass<T> item)
{
Type type = typeof(SomeClass<T>);
if (!list.ContainsKey(type))
list[type] = new List<SomeClass<T>>();
var l = (List<SomeClass<T>>)list[type];
l.Add(item);
}
public void Method<T>(SomeClass<T> obj)
{
Add(obj);
}
readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
}
test it with the following:
class Program
{
static void Main(string[] args)
{
var c = new C();
var sc1 = new SomeClass<int>();
var sc2 = new SomeClass<String>();
c.Method(sc1);
c.Method(sc2);
c.Method(sc1);
c.Method(sc2);
}
}
Personally, I would do this where possible; move the generic parameter from the method, to the class.
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.