How would you assign a list to a generic list since they are not the same type.
If I have a generic list:
List<T> myList = new List<T>();
and I have another list
List<OtherType> otherList = new List<OtherType>();
After I fill otherList with values. What are ways I can assign otherList to the generic list? Preferably without using a foreach.
if they are the same type you can do a basic type conversion
if(typeof(T) == typeof(OtherType))
myList = otherList as List<T>;
But that would make no sense, so I'd imagine you need some kind of conversion, problem is we need to specify that T is assignable from your base class
public static class StaticFoo
{
public static List<T> Foo<T>() where T : class
{
List<MyOtherClass> returnList = new List<MyOtherClass>() { new MyOtherClass() };
if(typeof(T).IsAssignableFrom(typeof(MyOtherClass)))
return returnList.Select(x => x as T).ToList();
throw new Exception($"Cannot convert {typeof(T)} to MyOtherClass");
}
}
public class MyClass { }
public class MyOtherClass : MyClass { }
The above code will work if you call it with T = MyClass or any other class that myOtherClass can be cast to. Alternatively you might want a concrete conversion method for a set of predefined types, it's kind of hacky but you could do something like this
public static class StaticFoo
{
public static List<T> Foo<T>() where T : class
{
List<MyOtherClass> returnList = new List<MyOtherClass>() { new MyOtherClass() };
return returnList.Select(x => x.Convert(typeof(T)) as T).ToList();
}
}
public class MyOtherClass {
public object Convert(Type type) {
if (type == typeof(string)) //more if statements for more types
return this.ToString(); //just an example
throw new NotImplementedException($"No cast available for type {type}");
}
}
Some context for the relationship between the generic type and your concrete class would be helpful
edit:
some advice that ignores your actual question. Most likely, you want to create an interface and return a list of that interface (I'm assuming that will match your use case more closely). Alternatively just change the signature to return List< object> - then you can do
return otherList.ToList<object>();
List<T> is invariant, so you can only assign lists of the same type. The closest you can come is creating a new list with the same items.
List<T> list = otherList.Select( x => (T)x ).ToList();
Consider a situation:
I have a method which use DataRow:
public void MyMethod (DataRow input)
{
DoSomething(input["Name1"]);
}
But now I have some another input types with indexer which I want to pass to this method. St like:
public void MyMethod (AnyTypeWithIndexer input)
{
DoSomething(input["Name1"]);
}
But I haven't found anything like that. I tried IDictionary but it didn't work.
Is there any super type st like "Indexable" or anything with which I can replace the "AnyTypeWithIndexer"?
Note: I still need this method to pass the DataRow and also my custom class (which I want to implement).
Can anybody help?
Thanks.
No, unfortunately, there is no interface that automatically applies to "all classes with an indexer that takes a string argument and returns an object".
What you can do, however, is to create a "proxy class" that implements such an interface
yourself:
public interface IStringToObjectIndexable
{
object this[string index] { get; set; }
}
class DataRowWrapper : IStringToObjectIndexable
{
private readonly DataRow row;
public DataRowWrapper(DataRow row) => this.row = row;
public object this[string index]
{
get => row[index];
set => row[index] = value;
}
}
MyMethod can now be declared as follows:
public void MyMethod(IStringToObjectIndexable input)
{
DoSomething(input["Name1"]);
}
// Compatibility overload
public void MyMethod(DataRow input) => MyMethod(new DataRowWrapper(input));
You can use dynamic type, but you will need to be noticed about the disadvantages of dynamic, such as performance drawbacks because of DLR, and the fact that type safety should be on your shoulders
public class WithIndexer
{
public int this[string key] => 42;
}
public static async Task Main()
{
Dictionary<string, int> a = new Dictionary<string, int>();
a.Add("meow", 41);
Foo(a, "meow");
Foo(new WithIndexer(), "key");
}
private static void Foo(dynamic indexed, string key)
{
Console.WriteLine(indexed[key]);
}
Output:
41
42
I'm experimenting with extending classes and managed to extend List<T> for fun like so:
public static void SomeCustomSort<T>(this List<T> list, string item)
{
if (typeof(T) != typeof(string) || list.Count == 0)
return;
// doStuff();
}
I wondered if there was a smarter way to extend List<T> only for List<string> so that my extension method is not listed or accessable for any other type T
Just make your method non-generic:
public static void SomeCustomSort(this List<string> list, string item)
and specify exact type it should work with
NOTE: With void methods even if you want to restrict extension method parameter to some set of types (e.g. all implementors of some interface or some non-sealed class with classes derived from it) I would not recommend using generic method with parameter constraint:
public static void SomeCustomSort<T>(this List<T> animals)
where T: IAnimal
Why? Because it overcomplicates your code. Non-generic method is more simple to understand than generic method. Generic method without constraint is more simple to understand than generic method with constraint. You should start from the simplest solution which is easy to understand. What sounds more natural to you?
"It sorts list of animals"
"It sorts list of items of any type"
"It sorts list of items of any type which is animal"
When to use generic type constraint? When you return items from your method and you don't want to lose information about the exact type of list items. Consider method which returns animals by some weight filter
public static IEnumerable<IAnimal> WhereWeightBelow(this List<IAnimal> animals, int weight)
If you'll pass list of dogs to this method, you will lose intellisense for all dog-specific information in the method output.
dogs.WhereWeightBelow(10).Where(d => d. /* oops only IAnimal members here */)
Returning generic type will preserve all dog info for you.
Another alternative not yet mentioned:
public static void SomeCustomSort<T>(this List<T> list, string item)
where T: YourSpecificType
This allows you to specify more than just one type, for example:
public static void SomeCustomSort<T>(this List<T> list, string item)
where T: ISortable, ICustomInterface
Just specify T instead of making it a generic method.
public static void SomeCustomSort(this List<string> list, string item)
Just define exactly string type on your extension method
public static void SomeCustomSort(this List<string> list, string item)
{
// doStuff();
}
You can also use a constraint like this (in this example T would have to be of type Project):
public static void SomeCustomSort<T>(this List<T> list, string item)
where T : Project
{
}
I would show you in the following example how you can easily expand a generic list.
I expanded the list to return random data from the list itself.
We have a class for example:
public class ExampleClass
{
public string Name { get; set; }
}
We have now made a list of these classes in some method:
var exampleList = new List<ExampleClass>()
{
new ExampleClass()
{
Name = "Class1"
},
new ExampleClass()
{
Name = "Class2"
},
new ExampleClass()
{
Name = "Class3"
}
};
var randomList = exampleList.Random(2);
The following is a simple implementation of returning random objects from a list
public static class ListExtensions
{
public static IList<T> Random<T>(this IList<T> list, int numberOfResult) where T : class
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (numberOfResult <= 0 || numberOfResult > list.Count) throw new ArgumentOutOfRangeException(nameof(numberOfResult));
var random = new Random();
var randomList = new List<T>();
var randomNumbers = new List<int>();
while (randomList.Count < numberOfResult)
{
var index = random.Next(list.Count);
if (randomNumbers.IndexOf(index) < 0)
{
randomNumbers.Add(index);
randomList.Add(list[index]);
}
}
return randomList;
}
}
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;
}
}
}
To simplify using a specific type of dictionary I have derived a class from the generic Dictionary<> to handle assorted elements derived from a common base class:
//my base class holding a value
public abstract class A{ public int aValue; }
//derived classes that actually are stuffed into the dictionary
public class B : A {...}
public class C : A {...}
//wrapper class for dictionary
public class MyDict : Dictionary<string, A>;
//my class using the dictionary
public class MyClass {
public MyDict dict = new MyDict();//use an instance of MyDict
public MyClass() { ... //fill dict with instances of B and C }
//function to return all elements of dict having a given value
public MyDict GetSubSet(int testVal) {
var ret = dict.Where(e => e.Value.aValue == testVal).
ToDictionary(k => k.Key, k => k.Value);
return (MyDict) ret; // <- here I get a runtime InvalidCastException
}
}
Before wrapping the generic Dictionary in the MyDict-class the cast succeeded (if I replace all instances of MyDict with Dictionary<string,int>, the code works fine, even without casting in the return statement).
I have also tried to cast the result using return ret as MyDict; but that will return a null value. Casting through object like this: return (MyDict) (object) ret; also fails with an InvalidCastException.
Anybody have an idea how to cast/convert the return value correctly?
You get an invalid cast exception because the result of ToDictionary is not MyDict. In order to fix this problem, add a constructor to MyDict that takes an IDictionary<string,A>, and return the result of calling that constructor from your GetSubSet method:
public class MyDict : Dictionary<string, A> {
public MyDict() {
// Perform the default initialization here
...
}
public MyDict(IDictionary<string,A> dict): base(dict) {
// Initialize with data from the dict if necessary
...
}
}
...
public MyDict GetSubSet(int testVal) {
var ret = dict.Where(e => e.Value.aValue == testVal).
ToDictionary(k => k.Key, k => k.Value);
return new MyDict(ret);
}