In C# some collections such as ArrayList and HashTable have generic alternatives which are List<T> and Dictionary<TKey, TValue>.
Does Array also have a generic alternative?
No - just use a strongly typed array, e.g. int[]. It's relatively rare to use a "weakly typed" Array in the first place - in fact, I don't believe you can really create one. Every Array is really a strongly-typed one, even if you don't refer to it that way.
If you're looking for the generic collection type that most closely resembles an array, then you probably want a List<T>. But it's not really the same thing.
To expand on what others have said: the point of having generic types is so that a programmer can then use type-specific instances of those generic types, based on the needs of the current program. Arrays are already type-specific. You can always just take a T[].
For example, look at this simple function definition:
void SomeFunction(int[] x)
You could also think of it like this:
void SomeFunction<T>(T[] x)
where the programmer just chose to call it with an int for the type parameter:
SomeFunction<int>(myIntArray)
Array has always been, with special compiler support, somewhat generic.
E.g. System.Array allows objects in, but an int[] does not.
Expanding on Jon's answer
Arrays have no generic alternative because it's perfectly fine to have a generic array.
public static T[] CreateArray<T>(T item1, T item2) {
T[] array = new T[2];
array[0] = item1;
array[1] = item2;
return array;
}
There is no need for a generic alternative as when you define an array you state the type of the array. All the classes you mentioned are simple collection classes. An aray is a totally different data structure.
Related
I'm trying to understand the design decision behind this part of the language. I admit i'm very new to it all but this is something which caught me out initially and I was wondering if I'm missing an obvious reason. Consider the following code:
List<int> MyList = new List<int>() { 5, 4, 3, 2, 1 };
int[] MyArray = {5,4,3,2,1};
//Sort the list
MyList.Sort();
//This was an instance method
//Sort the Array
Array.Sort(MyArray);
//This was a static method
Why are they not both implemented in the same way - intuitively to me it would make more sense if they were both instance methods?
The question is interesting because it reveals details of the .NET type system. Like value types, string and delegate types, array types get special treatment in .NET. The most notable oddish behavior is that you never explicitly declare an array type. The compiler takes care of it for you with ample helpings of the jitter. System.Array is an abstract type, you'll get dedicated array types in the process of writing code. Either by explicitly creating a type[] or by using generic classes that have an array in their base implementation.
In a largish program, having hundreds of array types is not unusual. Which is okay, but there's overhead involved for each type. It is storage required for just the type, not the objects of it. The biggest chunk of it is the so-called 'method table'. In a nutshell, it is a list of pointers to each instance method of the type. Both the class loader and the jitter work together to fill this table. This is commonly known as the 'v-table' but isn't quite a match, the table contains pointers to methods that are both non-virtual and virtual.
You can see where this leads perhaps, the designers were worried about having lots of types with big method tables. So looked for ways to cut down on the overhead.
Array.Sort() was an obvious target.
The same issue is not relevant for generic types. A big nicety of generics, one of many, one method table can handle the method pointers for any type parameter of a reference type.
You are comparing two different types of 'object containers':
MyList is a generic collection of type List, a wrapper class, of type int, where the List<T> represents a strongly typed list of objects. The List class itself provides methods to search, sort, and manipulate its contained objects.
MyArray is a basic data structure of type Array. The Array does not provide the same rich set of methods as the List. Arrays can at the same time be single-dimensional, multidimensional or jagged, whilst Lists out of the box only are single-dimensional.
Take a look at this question, it provides a richer discussion about these data types: Array versus List<T>: When to use which?
Without asking someone who was involved in the design of the original platform it's hard to know. But, here's my guess.
In older languages, like C, arrays are dumb data structures - they have no code of their own. Instead, they're manipulated by outside methods. As you move into an Object oriented framework, the closest equivilent is a dumb object (with minimal methods) manipulated by static methods.
So, my guess is that the implementation of .NET Arrays is more a symptom of C style thinking in the early days of development than anything else.
This likely has to do with inheritance. The Array class cannot be manually derived from. But oddly, you can declare an array of anything at all and get an instance of System.Array that is strongly typed, even before generics allowed you to have strongly typed collections. Array seems to be one of those magic parts of the framework.
Also notice that none of the instance methods provided on an array massively modify the array. SetValue() seems to be the only one that changes anything. The Array class itself provides many static methods that can change the content of the array, like Reverse() and Sort(). Not sure if that's significant - maybe someone here can give some background as to why that's the case.
In contrast, List<T> (which wasn't around in the 1.0 framework days) and classes like ArrayList (which was around back then) are just run-of-the mill classes with no special meaning within the framework. They provide a common .Sort() instance method so that when you inherited from these classes, you'd get that functionality or could override it.
However, these kinds of sort methods have gone out of vogue anyway as extension methods like Linq's .OrderBy() style sorting have become the next evolution. You can query and sort arrays and Lists and any other enumerable object with the same mechanism now, which is really, really nice.
-- EDIT --
The other, more cynical answer may just be - that's how Java did it so Microsoft did it the same way in the 1.0 version of the framework since at that time they were busy playing catch-up.
One reason might be because Array.Sort was designed in .NET 1.0, which had no generics.
I'm not sure, but I'm thinking maybe just so that arrays are as close to Primitives as they can be.
I am writing a recursive discovery method, which will basically deserialize an object. This object is always a List of Dictionaries, but sometimes the dictionary will have other Dictionaries as values and sometimes the dictionary will have strings as values.
I need to declare the List at the beginning somehow. List<Dictionary<string,???>>
I am in a pickle at the moment, anybody know a solution?
Basically the closest you can come is probably List<IDictionary> (the non-generic IDictionary interface).
Given that the dictionaries can have different key and value types, you wouldn't be able to use them in a type-safe way at compile-time anyway.
You could wrap the Dictionary<> in a class so that it becomes a List< DictionaryWrapper >.
I currently have a class that holds 3 dictionaries, each of which contains Lists of the same type within each dictionary, but different types across the dictionaries, such as:
Dictionary1<string, List<int>> ...
Dictionary2<string, List<double>>...
Dictionary3<string, List<DateTime>>...
Is there a way to use a different collection that can hold all the Lists so that I can iterate through the collection of Lists? Being able to iterate is the only requirement of such collection, no sorting, no other operations will be needed.
I want to be able to access the List directly through the string or other identifier and access the List's members. Type safety is not a requirement but in exchange I do not want to have to cast anything, speed is the absolutely top priority here.
So, when calculations are performed on the list's members knowledge of the exact type is assumed, such as "double lastValue = MasterCollection["List1"].Last();", whereas it is assumed that List1 is a List of type double.
Can this be accomplished? Sorry that I may use sometimes incorrect or incomplete terminology I am not a trained programmer or developer.
Thanks,
Matt
To do that you would have to use a non-generic API, such as IList (not IList<T>) - i.e. Dictionary<string, IList>. Or since you just need to iterate, maybe just IEnumerable (not IEnumerable<T>). However! That will mean that you are talking non-generic, so some sacrifices may be necessary (boxing of value types during retrieval, etc).
With an IList/IEnumerable appraoch, to tweak your example:
double lastValue = MasterCollection["List1"].Cast<double>().Last();
You could, of course, write some custom extension methods on IDictionary<string,IList>, allowing something more like:
double lastValue = MasterCollection.Get<double>("List1").Last();
I'm not sure it is worth it, though.
No, what you are trying to do is not possible; namely, the requirement for strong-typing on all of the lists without casting is what's preventing the rest.
If your only requirement is to iterate through each of the items in the list, then you could create your dictionary as a Dictionary<string, IEnumerable> (note the non-generic interface). IEnumerable<T> derives from IEnumerable which would allow you to iterate through each item in the list.
The problem with this is that you would have to perform a cast at some point either to the IEnumerable<T> (assuming you know you are working with it) or use the Cast<T> extension method on the Enumerable class (the latter being worse, as you might incur boxing/unboxing, unless it does type-sniffing, in which case, you wouldn't have a performance penalty).
I would say that you shouldn't store the items in a single list; your example usage shows that you know the type ahead of time (you are assigning to a double) so you are aware at that point in time of the specific typed list.
It's not worth losing type-safety over.
When I do int[], string[], T[] - this is a generic array. An array is just an object like everything else.
So what is the actual open generic type of []? I assume it is just some syntactic sugar over something like Array<> but I haven't been able to find anything of the sort.
Bonus points if you can somehow answer this before Jon Skeet.
It's just System.Array; it isn't generic. See here for a brief discussion: http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx
Arrays are older that generics. Arrays are available since .net 1, and generics were only introduced in .net 2. So they are no syntax sugar on top of generics.
Instead they derive from Array and use a lot of runtime magic to work.
In addition arrays of a reference type support some variance patterns not supported by generics. If I recall correctly this was done for Java compatibility.
Far as I know, there wouldn't be an open generic type of Array; they existed before generics did in the .NET Framework. Arrays are just "weird"; the System.Array type exists mainly to provide O-O functionality to array objects. Only the runtime can derive from it.
HOWEVER, System.Array implements the generic IList<T>, which enforces the indexer. If you want an abstract that is strongly typed and will accept a strongly-typed array, use IList.
It's not just syntactic sugar, it's an actual derivation of the System.Array class.
I have in instance of class foo and i want to return it as IEnumerable.
Can i do it without creating a new list etc..
Perhaps something like the following:
IEnumerable<foo>.fromInstance(foo)
Options:
Create an instance of a collection class, like an array or a list. This would be mutable by default, which would be slightly unhelpful if this is a sequence you want to be able to hand out in your API. You could create a ReadOnlyCollection<T> wrapper around such a collection though.
Write your own iterator block as per Botz3000's answer
Use Enumerable.Repeat(item, 1) from LINQ, if you're using .NET 3.5.
The best answer here depends on the usage. If you only need this to call another method which uses a sequence, and you know it won't be modified, I'd probably use an array. For example, in order to call Concat on some other sequence, you might want:
var wholeList = regularList.Concat(new[] { finalValue });
I have confidence that Concat isn't going to mutate the array, and nothing else will ever see the reference to the array itself.
If you need to return the sequence to some other code, and you don't know what it might do with it, I'd probably use Enumerable.Repeat.
you could do this:
public IEnumerable<Foo> GetSingleFooAsEnumerable() {
yield return singleFoo;
}
The best idiomatic way to do this is something like new[] { foo } which just creates a 1-element array of whatever type foo is declared to be.
The one possible downside to this is that arrays aren't immutable, so somebody can cast your IEnumerable<T> to a T[] and change the value in there. This is fairly unlikely, though, so I don't worry about it.
IENumerable is supposed to be used for something that you can enumerate through, so using it for a single instance seems quite strange. If you really need to, you can get it done like this. It might be a better way, but this should get the job done:
List<foo> myList = new List<foo>();
myList.Add( myInstanceOfFoo );
IEnumerable myEnumerable = myList.AsEnumerable();
Regardless of how you see this, you are actually trying to make a list of one element, and then it's really no reason to make it a list.