Is there any established way of returning a read-only 2-d array in C#?
I know ReadOnlyCollection is the right thing to use for a 1-d array, and am happy to write my own wrapper class that implements a this[] {get}. But I don't want to reinvent the wheel if this wheel already exists.
Unfortunately there is no any built-in implementation to handle a case you ask for.
But a simple implementation on your own, shouldn't be something difficult.
The only think, I hope you aware of it, that you will do is a readonly collection, but not elements inside that collection.
Hope this helps.
There's only one way to simulate this.
You need to create your own class, with a private array.
The most similar implementation of an array is an indexer:
Using indexers
Indexers (C# programming guide)
10.8 Indexers (old)
C# 6.0 draft Indexers
The '10.8' link shows the simulation of a bidimensional array.
If you implement the indexer only with a getter, the user can only read the elements, but not write them. However, if each element is an object (reference type) you can't prevent the modification of the accessed objects properties.
However, there are several ways of simulating "read-only" objects:
Create a wrapper class that exposes the properties of each element in the array as read only properties, so that they cannot be modified
Using primitive value types (like int)
Defeating the changes by returning a copy of the element in the private array instead of the original element in the private array, so that, the changes made to the object don't affect the original object in the array.
In other languages like C++ there are references and pointers to constant values, but this doesn't exist in C#.
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.
Looking over the source of List<T>, it seems that there's no good way to access the private _items array of items.
What I need is basically a dynamic list of structs, which I can then modify in place. From my understanding, because C# 6 doesn't yet support ref return types, you can't have a List<T> return a reference to an element, which requires copying of the whole item, for example:
struct A {
public int X;
}
void Foo() {
var list = new List<A> { new A { X = 3; } };
list[0].X++; // this fails to compile, because the indexer returns a copy
// a proper way to do this would be
var copy = list[0];
copy.X++;
list[0] = copy;
var array = new A[] { new A { X = 3; } };
array[0].X++; // this works just fine
}
Looking at this, it's both clunky from syntax point of view, and possibly much slower than modifying the data in place (Unless the JIT can do some magic optimizations for this specific case? But I doubt they could be relied on in the general case, unless it's a special standardized optimization?)
Now if List<T>._items was protected, one could at least subclass List<T> and create a data structure with specific modify operations available. Is there another data structure in .NET that allows this, or do I have to implement my own dynamic array?
EDIT: I do not want any form of boxing or introducing any form of reference semantics. This code is intended for very high performance, and the reason I'm using an array of structs is to have them tighly packed on memory (and not everywhere around heap, resulting in cache misses).
I want to modify the structs in place because it's part of a performance critical algorithm that stores some of it's data in those structs.
Is there another data structure in .NET that allows this, or do I have to implement my own dynamic array?
Neither.
There isn't, and can't be, a data structure in .NET that avoids the structure copy, because deep integration with the C# language is needed to get around the "indexed getter makes a copy" issue. So you're right to think in terms of directly accessing the array.
But you don't have to build your own dynamic array from scratch. Many List<T>-like operations such as Resize and bulk movement of items are provided for you as static methods on type System.Array. They come in generic flavors, so no boxing is involved.
The unfortunate thing is that the high-performance Buffer.BlockCopy, which should work on any blittable type, actually contains a hard-coded check for primitive types and refuses to work on any structure.
So just go with T[] (plus int Count -- array length isn't good enough because trying to keep capacity equal to count is very inefficient) and use System.Array static methods when you would otherwise use methods of List<T>. If you wrap this as a PublicList<T> class, you can get reusability and both the convenience of methods for Add, Insert, Sort as well as direct element access by indexing directly on the array. Just exercise some restraint and never store the handle to the internal array, because it will become out-of-date the next time the list needs to grow its capacity. Immediate direct access is perfectly fine though.
Currently I have an class that contains an array and an integer.
I have millions of these objects, and would like to save memory by just having an array so I save 12 bytes for each object (by not having to allocate a class wrapper for each one). This will save a lot of memory.
Unfortunately, I need to store the integer as well. I was thinking about just storing it in the first index, but it is slightly messy. I was hoping I could just derive from an array and insert the int member in the subclass, but apparently that is disallowed by the compiler.
Are there any alternatives? I suppose I could just copy and paste the array class from the referencesource framework and add my property, but it seems like overkill.
You can't derive from an array (and "copy and paste the array class from the reference source framework" will likely not do you much good as arrays are very integrated into language/framework).
One option may be to use struct with integer and array - you'll get major pain to deal with struct, but if careful it will provide you exactly what you looking for (if your "integer value" is mutable or the array needs to change size - I'd strongly recommend forgetting you've seen such suggestion).
I have a class that's going to hold 3 parallel arrays. (For a class assignment we're basically coding a rudimentary xml parser...beginning programming class)
*Note, I'm doing this in very basic OOP. I've got an XMLObject class which has the arrays, and holds the xml elements in one array, the data values in another, and the ending elements in the third. I've also got an XMLParse object that does the actual parsing, and stores the strings to their various arrays as it finds them. I've been forbiddin from using .net's xml stuff for this assignment, has to be a byte by byte read in.
Now I was reading on MSDN about indexers, and as I understand it, I can either only have one array using an indexer(since that's the only way for properties to receive parameters), or I have to make my arrays public so that the parse class can add to them, and main or another class can read from them.
Do I have that right or am I missing something/not understanding how to get and set arrays of one class from another?
Does the same go for list as well?
If I understand your question you want to have many indexers on your class which will return the various elements from the arrays that the class holds.
you can have many indexers, but only if the type used by each indexer is different. So you could have an indexer by int and an indexer by string, but not 2 indexers by int.
From the sounds of things you won't be able to use indexers to access all the values your class holds, as they will probably all want to use int.
Publicly exposing the arrays is one option, but you could also provide different methods for reading each thing, so you could have GetXmlElement(int index), GetDataValue(int index) and GetEndingElement(int index) to provide access to the contents of the arrays.
Another option would be to store the data in arrays internally, but accept and return a class which bundled up all the data together. This way you could have a single indexer which returned all the data, as all the data would be a single object with the element, data value and end element in it.
you would have to provide similar methods for adding data and potentially removing and changing as well. Whether you want to do this, opr just exopse the underlying arrays/lists depends on if you want to be able to exercise control over the adding/accessing/deleting/changing of the arrays or not.
I suggest you use List<T> instead of array for storing the data. It is much easier to work with.
See here.
I was reading XNA library code and inside the type VertexPositionColor, they supress the CA2105:ArrayFieldsShouldNotBeReadOnly message with the justification "The performance cost of cloning the array each time it is used is too great."
public struct VertexPositionColor
{
public static readonly VertexElement [ ] VertexElements;
}
But why would it be copied when it's used? This only happens for structs where the accessed property/field is a ValueType, right?
I guess they are justifying the fact that they are exposing an array field more than anything else and the underlying reason of why they are doing so is performance:
The alternative they probably had in mind was making the array field private with a property exposing an IEnumerable or returning a copy of the array each time the property was accesed.
EDIT. Edited the answer a little to make clearer what I was trying to say :p.
In most cases they'd be better off using Array.AsReadOnly and returning a generic ReadOnlyCollection. According to the documentation that's an O(1) operation.
In the current implementation callers can change the values in the array (modifying the static/global state directly).
One more reason to read Framework Design Guidelines - it gives you the reasons behind FxCop's recommendations.