I noticed this code in our project
Dictionary<int, IList> someDict = new Dictionary<int, IList>();
What's the idead of using interface for value? Does that means that I can put in every list that implements/support IList ? For example, can I put L List<int>and List<string> for values in the dictionary ?
It allows you to have a more generic type, so it will become easier to refactor if you change the type later.
List<T> or IList<T>
The best way to reduce refactoring job is to use IEnumerable when possible.
You can put any implementation of IList as a value
Dictionary<int, IList> someDict = new Dictionary<int, IList>();
someDict[1] = new List<string>() { "Hello", "World" };
someDict[2] = new List<int>() { 42 };
someDict[3] = new int[] { 1, 2, 3 };
someDict[4] = new ArrayList();
Yes, you want to be decoupled from a special class, you just want to make sure that the type used in the dictionary provides the IList funcionality. As long as your type provides this you can use it, including List<T>. It's like a contract which ensures a set of methods/properties on the type
Yes, you can use types that inherit from from type declared. In your case List<int> is generic type built from List<T>, which in turn inherits from IList. For that reason, yes, you can use List<int> in your dictionary.
Related
This question already has answers here:
IDictionary<TKey, TValue> in .NET 4 not covariant
(6 answers)
Closed 4 months ago.
Why doesn't this work in C#?
var dict1 = new Dictionary<int, System.Collections.IEnumerable>();
dict1[0] = new List<string>(); // OK, because implements IEnumerable
var dict2 = new Dictionary<int, List<string>>();
dict1 = (Dictionary<int, System.Collections.IEnumerable>)dict2; // Compiler error CS0030
We can clearly see that every value in dict2 must implement IEnumerable because it is a List<T>, so why can't I assign it to a Dictionary<int, System.Collections.IEnumerable>? Is there a way to do this?
My use case here is that I have some code that wants to use the more specific stuff in (in this example) the List<string>, but some other code that needs to take an IEnumerable dictionary. I can explicitly cast in every predicate to get access to the more specific stuff, but it seems pretty messy and I'd rather have a reference to the (same) Dictionary where its value's type is actually List<string>:
var dict1 = new Dictionary<int, System.Collections.IEnumerable>();
dict1[0] = new List<string>(); // OK, because implements IEnumerable
var result = dict1.Where(x => ((List<string>)x.Value).Capacity > 100);
Take your code a step further and you'll see why:
var dict1 = new Dictionary<int, System.Collections.IEnumerable>();
dict1[0] = new List<string>(); // OK, because implements IEnumerable
var dict2 = new Dictionary<int, List<string>>();
dict1 = (Dictionary<int, System.Collections.IEnumerable>)dict2;
dict1.Add(1, new ArrayList());
ArrayList implements IEnumerable so, based on the type of dict1, that should work. It won't though, because the underlying object will only accept List<string> objects. Such situations would be all too common if what you describe were to be allowed.
I was able to achieve this using a generic type constraint. My containing class now says:
public class MyClass<TId, TValue>
where TId : struct
where TValue : System.Collections.IEnumerable {
[...]
public Dictionary<TId, TValue> Field;
[...]
}
This allows me to set the Field Dictionary to be of the type that I want as long as it implements IEnumerable, so when I want to use that specific type's abilities, I can, but when the containing class wants to use IEnumerable from that Dictionary, it can too:
var test = new MyClass();
test.Field = new Dictionary<int, List<string>>();
I want to access members of lists passed in as "object" (the function is handling other data types such as arrays as well). Unfortunately, while this works:
List<object> objectlist = new List<object> { "1", "2" };
object res = ((List<object>)((object)objectlist))[0];
this does not:
List<string> strlist = new List<string> { "1", "2" };
res = (string)((List<object>)((object)strlist))[0];
though it DOES work with arrays.
It does not appear to be possible to convert regular lists to List.
Is using reflection (but with GetMethods to avoid repeated string searches):
MethodInfo info = ((object)list).GetType().GetMethod("get_Item");
object s1 = (object)info.Invoke(((object)list), new object[] { 0 });
the only way to do this?
No, a List<string> isn't a List<object>... although it is an IEnumerable<object> due to generic covariance. However, a List<int> isn't even an IEnumerable<object> as covariance doesn't apply to value type type arguments. Fortunately, it is an IEnumerable.
So to get the first element of an arbitrary object which you know implements IEnumerable, I'd just use:
object first = ((IEnumerable) source).Cast<object>().First();
(Due to IEnumerator not implementing IDisposable, more "manual" ways of doing it end up being a bit fiddly.)
List<T> implements non-generic IList. If you only want to retrieve items from the list, you can cast to it. One-dimensional arrays implement it too, so the cast will work for both arrays and lists
res = (string)((IList)((object)strlist))[0];
Run into term Anti-patterns in programming, and one of examples was this.
IList values = new ArrayList(); //Anti-pattern, bad
ArrayList values = new ArrayList(); //good
What is the difference between this two variants? Aren't they the same, same as with using var keyword?
I assume by List you really mean IList.
IList values = new ArrayList(); just lets you view the ArrayList object as an IList object. You could cast back to ArrayList if you wanted.
ArrayList values = new ArrayList() is the same as var values = new ArrayList()
Neither is really an anti-pattern. If all you need is the methods that IList provides, it's considered good practice to only declare the type of object you need to use, regardless of what you assign it. This is more important in the public interface of a type. As a local variable; it doesn't really matter either way.
In this isolation, it is mostly irrelevant.
List values = new ArrayList();
ArrayList values = new ArrayList();
var values = new ArrayList();
because here, values is declared inside a method body, and we do not care much about abstraction or isolation.
But I agree, that assigning to a List just puts a restriction to the use of values that has no advantage. One might say, this is an AnitPattern, but there are much more relevant AntiPatterns.
ArrayList and var are better, var will most often be most readable and maintainable. I personally would use var.
As an aside, hardly anyone uses these collections anymore, ArrayList is sometimes prefered to List, but I personally use the latter also here.
The advantage with IList is there are many different classes that can be assigned to it. This can be handy if you're sourcing data from different places that use different classes.
IList values;
values = new ArrayList();
values = new object[] {};
values = new List<int>();
values = new DataView();
However, if you use an IList, you can only use the methods defined by an IList. If you define the variable as an ArrayList or any other concrete class, you have access to all of that class's methods.
ArrayList values = new ArrayList();
values.
Using the var keyword will tell the compiler to use the same class as the result of the expression. It can be very useful if you have a very long-winded class.
var values = new ArrayList();
// values is ArrayList
// Assuming a function: List<int> GetIntegerList() { ... }
var values = GetIntegerList();
// values is List<int>
// Assuming a function: Dictionary<string, Dictionary<string, List<Tuple<int, int, string>>>> GetSettingsCollection() { ... }
var values = GetSettingsCollection();
// values is Dictionary<string, Dictionary<string, List<Tuple<int, int, string>>>>
List<struct {string, string, double} > L = new List<struct {string, string, double}>;
L.Add({"hi", "mom", 5.0});
What is the nicest way to get this functionality in C#? I want to define a strongly-typed tuple on the fly (for use in a local function), save a bunch of them in a list, do some processing and return a result, never to touch the list again.
I don't actually care about the strong typing, but a List of vars doesn't work. Do I want a list of objects? Is that the closest I can get?
Defining structs or classes for temporary data structures seems verbose and pedantic to me.
The best way to represent this in C# is to use the Tuple type
var l = new List<Tuple<string, string, double>>();
l.Add(Tuple.Create("hi", "mom", 42.0));
There's no explicit language support for tuples but as you can see the API isn't too wordy
var arr = new[] { Tuple.Create("hi","mom", 5.0) };
is the easiest; this is actually an array, but a list is easy enough too - perhaps .ToList() if you feel lazy.
Personally, in this scenario I'd use an anon-type:
var arr = new[] { new { Text = "hi", Name = "mom", Value = 5.0 } };
Very similar, except the member-names are more meaningful.
List<Tuple<string, string, double>> L = new List<Tuple<string, string, double>>();
L.Add(Tuple.Create("hi", "mom", 5.0));
More on the Tuple class.
You can also take a look at using anonymous types as an alternative to Tuples.
Example initialization of array of anon types and looping over the result:
var anons = new [] { new {num=1, str="str1"},
new {num=2, str="str2"} };
foreach(var v in anons) Console.WriteLine(v.num + " " + v.str);
If you are using C# 4.0, you can use the Tuple type
Have you looked at the Tuple class, introduced in .NET 4.0?
Another option is to use anonymous types.
The simplest way I can think of would be to use Tuples:
var L = new List<Tuple<string, string, double>>();
L.Add(Tuple.Create("a", "b", 10D));
Alternatively you could also use a list of dynamics
I want to create a new instance of an object IEnumerable<object>
Can I do this?
IEnumerable<object> a = new IEnumerable<object>();
You can for example create an instance of List<object>, which implements IEnumerable<object>. Example:
List<object> list = new List<object>();
list.Add(1);
list.Add(4);
list.Add(5);
IEnumerable<object> en = list;
CallFunction(en);
Another solution would be to use Empty<T>.
msdn extract:
Returns an empty IEnumerable that has the specified type argument.
IEnumerable<object> a = Enumerable.Empty<object>();
There is a thread on SO about it: Is it better to use Enumerable.Empty() as opposed to new List to initialize an IEnumerable?
If you use an empty array or empty list, those are objects and they are stored in memory. The Garbage Collector has to take care of them. If you are dealing with a high throughput application, it could be a noticeable impact.
Enumerable.Empty does not create an object per call thus putting less load on the GC.
Since you now specified you want to add to it, what you want isn't a simple IEnumerable<T> but at least an ICollection<T>. I recommend simply using a List<T> like this:
List<object> myList=new List<object>();
myList.Add(1);
myList.Add(2);
myList.Add(3);
You can use myList everywhere an IEnumerable<object> is expected, since List<object> implements IEnumerable<object>.
(old answer before clarification)
You can't create an instance of IEnumerable<T> since it's a normal interface(It's sometimes possible to specify a default implementation, but that's usually used only with COM).
So what you really want is instantiate a class that implements the interface IEnumerable<T>. The behavior varies depending on which class you choose.
For an empty sequence use:
IEnumerable<object> e0=Enumerable.Empty<object>();
For an non empty enumerable you can use some collection that implements IEnumerable<T>. Common choices are the array T[], List<T> or if you want immutability ReadOnlyCollection<T>.
IEnumerable<object> e1=new object[]{1,2,3};
IEnumerable<object> e2=new List<object>(){1,2,3};
IEnumerable<object> e3=new ReadOnlyCollection(new object[]{1,2,3});
Another common way to implement IEnumerable<T> is the iterator feature introduced in C# 3:
IEnumerable<object> MyIterator()
{
yield return 1;
yield return 2;
yield return 3;
}
IEnumerable<object> e4=MyIterator();
No you can't since IEnumerable is an interface.
You should be able to create an empty instance of most non-interface types which implement IEnumerable, e.g.:-
IEnumerable<object> a = new object[] { };
or
IEnumerable<object> a = new List<object>();
No, You cannot do that. Use the following line of code instead:
IEnumerable<int> usersIds = new List<int>() {1, 2, 3}.AsEnumerable();
I hope it helps.
The main reason is we can't create object of an interface, and IEnumerable is an interface.
We need to create object of the class which implements the interface. This is the main reason we can't directly create object of IEnumerable.
You can do this:
IEnumerable<object> list = new List<object>(){1, 4, 5}.AsEnumerable();
CallFunction(list);
I wanted to create a new enumerable object or list and be able to add to it.
This comment changes everything. You can't add to a generic IEnumerable<T>. If you want to stay with the interfaces in System.Collections.Generic, you need to use a class that implements ICollection<T> like List<T>.
No IEnumerable is an interface, you can't create instance of interface
you can do something like this
IEnumerable<object> a = new object[0];
It's a pretty old question, but for the sake of newcomers, this is how we can protect an IEnumerable<T> from a null exception. Another word, to create an empty instance of a variable of type IEnumerable<T>
public IEnumerable<T> MyPropertyName { get; set; } = Enumerable.Empty<T>();
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.empty?view=net-5.0
Cheers.
I have been Implementing IEnumerable of type IEnumerable<T> by this way
IEnumerable<T> MyEnum = new T[]{ /*object of type T*/ };
Example:
var Object = new Book{id = 1,name = "Hello World"};
IEnumerable<Book> MyEnum = new Book[]{ Object };