int[] type and documentation - arrays

I'm puzzled about arrays in C#.
I can't find any documentation on MSDN about for example the object double[].
I do find documentation about int, array, collections, ... but can't find out of what type double[] is. If I do double[] a = new double[10]; a.GetType(), I find that the type of a is System.Double[]
I believe that the type is not System.Double[], but must be some descendent of an object or interface in the System.Collections namespace or the System.Collections.Generic namespace. My best guess is that a double[] is a type that implements the interface System.Collections.IList, but I'm not sure at all.
So, could anyone explain me what kind of object an array of doubles (so an object double[]) really is? What are it's base classes, which interfaces does it implement, ...
Where could I find documentation on arrays of objects defined as int[], ..., object[] ?
Thanks!

Array is a base class for all types of arrays int, double, string whatever, the base class for System.Array is System.Object. so the correct type is System.Double[]. It implements the ICloneable,
IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable interfaces as stated on msdn.
The main difference between arrays and collection is that arrays cannot be changed in size at runtime and arrays have to contain objects of same type as opposed to collections.

Related

Is there a technical reason why I cannot declare a public array in a VBA class?

I just discovered that it's apparently not possible to declare a public array in a VBA class while it is fine to declare it private.
I am wondering if this is has a technical reason or if this is a design choice on Microsoft's part.
Either explanation doesn't make much sense to me: I cannot see a technical reason that would prevent a member to be private while it can be public as this is only an access check that is checked at runtime.
On the other hand, I don't understand why it shouldn't be possible to declare public arrays while it is perfectly fine to declare public integers or other data types.
I'd appreciate if someone could explain the rational behind all this.
I believe you'd need to ask the persons who created the Visual Basic (or maybe even Basic) programming language as to "why". It seems to be inherent to the languages. As far as VBA goes, the restriction comes from VB6, on which VBA bases. I find this reference in a Google search:
Declaring data as Public in a Form means you are creating a Property
on that Form, using abbreviated syntax. A Property cannot be an array
using that shortcut syntax.
To say this another way, "Public" only means "global" for
old-fashioned static (BAS) modules. For everything else Public means
something entirely different.
And this:
Instead of Arrays, You can use Collection object or Your own
Collection Class. VB6 does not allow to declare Constants, Arrays,
User Defined Types as Public.
From the VBA Help topic Constants, fixed-length strings, arrays, user-defined types, and Declare statements not allowed as Public members of an object module
Not all variables in an object module can be declared as Public.
However, procedures are Public by default, and Property procedures can
be used to simulate variables syntactically. This error has the
following causes and solutions:
Concerning arrays, specifically
You declared a Public array in an object module. Although a procedure
can't return an array, it can return a Variant that contains an array.
To simulate a Public array in a class module, use a set of Property
procedures that accept and return a Variant containing an array.

Why does a System.Array object have an Add() method?

I fully understand that a System.Array is immutable.
Given that, why does it have an Add() method?
It does not appear in the output of Get-Member.
$a = #('now', 'then')
$a.Add('whatever')
Yes, I know this fails and I know why it fails. I am not asking for suggestions to use [System.Collections.ArrayList] or [System.Collections.Generic.List[object]].
[System.Array] implements [System.Collections.IList], and the latter has an .Add() method.
That Array implements IList, which is an interface that also covers resizable collections, may be surprising - it sounds like there are historical reasons for it[1]
.
In C#, this surprise is hard to stumble upon, because you need to explicitly cast to IList or use an IList-typed variable in order to even access the .Add() method.
By contrast, since version 3, PowerShell surfaces even a type's explicit interface implementations as direct members of a given type's instance. (Explicit interface implementations are those referencing the interface explicitly in their implementation, such as IList.Add() rather than just .Add(); explicit interface implementations are not a direct part of the implementing type's public interface, which is why C# requires a cast / interface-typed variable to access them).
As a byproduct of this design, in PowerShell the .Add() method can be called directly on System.Array instances, which makes it easier to stumble upon the problem, because you may not realize that you're invoking an interface method. In the case of an array, the IList.Add() implementation (rightfully) throws an exception stating that Collection was of a fixed size; the latter is an exception of type NotSupportedException, which is how types implementing an interface are expected to report non-support for parts of an interface.
What helps is that the Get-Member cmdlet and even just referencing a method without invoking it - simply by omitting () - allow you to inspect a method to determine whether it is native to the type or an interface implementation:
PS> (1, 2).Add # Inspect the definition of a sample array's .Add() method
OverloadDefinitions
-------------------
int IList.Add(System.Object value)
As you can see, the output reveals that the .Add() method belongs to the Ilist interface.
[1] Optional reading: Collection-related interfaces in .NET with respect to mutability
Disclaimer: This is not my area of expertise. If my explanation is incorrect / can stand improvement, do tell us.
The root of the hierarchy of collection-related interfaces is ICollection (non-generic, since v1) and ICollection<T> (generic, since v2).
(They in turn implement IEnumerable / IEnumerable<T>, whose only member is the .GetEnumerator() method.)
While the non-generic ICollection interface commendably makes no assumptions about a collection's mutability, its generic counterpart (ICollection<T>) unfortunately does - it includes methods for modifying the collection (the docs even state the interface's purpose as "to manipulate generic collections" (emphasis added)). In the non-generic v1 world, the same had happened, just one level below: the non-generic IList includes collection-modifying methods.
By including mutation methods in these interfaces, even read-only/fixed-size lists/collections (those whose number and sequence of elements cannot be changed, but their element values may) and fully immutable lists/collections (those that additionally don't allow changing their elements' values) were forced to implement the mutating methods, while indicating non-support for them with NotSupportedException exceptions.
While read-only collection implementations have existed since v1.1 (e.g, ReadOnlyCollectionBase), in terms of interfaces it wasn't until .NET v4.5 that IReadOnlyCollection<T> and IImmutableList<T> were introduced (with the latter, along with all types in the System.Collections.Immutable namespace, only available as a downloadable NuGet package).
However, since interfaces that derive from (implement) other interfaces can never exclude members, neither IReadOnlyCollection<T> nor IImmutableCollection<T> can derive from ICollection<T> and must therefore derive directly from the shared root of enumerables, IEnumerable<T>.
Similarly, more specialized interfaces such as IReadOnlyList<T> that implement IReadOnlyCollection<T> can therefore not implement IList<T> and ICollection<T>.
More fundamentally, starting with a clean slate would offer the following solution, which reverses the current logic:
Make the major collection interfaces mutation-agnostic, which means:
They should neither offer mutation methods,
nor should they make any guarantees with respect to immutability.
Create sub-interfaces that:
add members depending on the specific level of mutability.
make immutability guarantees, if needed.
Using the example of ICollection and IList, we'd get the following interface hierarchy:
IEnumerable<T> # has only a .GetEnumerator() method
ICollection<T> # adds a .Count property (only)
IResizableCollection<T> # adds .Add/Clear/Remove() methods
IList<T> # adds read-only indexed access
IListMutableElements<T> # adds writeable indexed access
IResizableList<T> # must also implement IResizableCollection<T>
IResizableListMutableElements<T> # adds writeable indexed access
IImmutableList<T> # guarantees immutability
Note: Only the salient methods/properties are mentioned in the comments above.
Note that these new ICollection<T> and IList<T> interfaces would offer no mutation methods (no .Add() methods, ..., no assignable indexing).
IImmutableList<T> would differ from IList<T> by guaranteeing full immutability (and, as currently, offer mutation-of-a-copy-only methods).
System.Array could then safely and fully implement IList<T>, without consumers of the interface having to worry about NotSupportedExceptions.
To "Add" to #mklement0's answer: [System.Array] implements [System.Collections.IList] which specifies an Add() method.
But to answer why have an Add() if it doesn't work? Well, we haven't looked at the other properties, i.e. IsFixedSize :
PS > $a = #('now', 'then')
PS > $a.IsFixedSize
True
So, a [System.Array] is just a [System.Collections.IList] that is a Fixed Size. When we look back at the Add() method, it explicitly defines that if the List is Read-Only or Fixed Size, throw NotSupportedException which it does.
I believe the essence is not, "Let's have a function that just throws an error message for no reason", or to expand on it, No other reason than to fulfill an Interface, but it actually is providing a warning that you are legitimately doing something that you shouldn't do.
It's the typical Interface ideas, you can have an IAnimal type, with an GetLeg() method. This method would be used 90% of all animals, which makes it a good reason for implementing into the base Interface, but would throw an error when you use it against a Snake object because you didn't first check the .HasFeet property first.
The Add() method is a really good method for a List Interface, because it is an essential method for Non-Readonly and Non-Fixed length lists. We are the ones being stupid by not checking that the list is not IsFixedSize before calling an Add() method that would not work. i.e. this falls into the category of $null checks before trying to use things.

Kotlin array types and class literals

I am trying to deserialize an array of JSON objects with GSON. So the simple call:
val arrayOfFoo = gson.fromJson(source, Array<Foo<*>>::class.java>)
should do the trick. But type erasure tells us, that Foo<*> does not exist at runtime, so the error "Only class literals are allowed on the left hand side of a class literal" pops up. Well, so the solution must be:
val arrayOfFoo = gson.fromJson<Array<Foo<*>>>(source, Array::class.java)
Unfortunatelly, now the Kotlin compiler magic - that turns arrays of Wrapper types into primitive arrays - can not be sure what to do and tells us:
"Array class literals require a class type. Please specify one in angle brackets".
But, wait: This is, what did not work a second ago. Using
Array<Foo>::class.java
does not work, too, since now the compiler tells us: "One type argument is expected for Foo".
I personally can not see a way to solve that. Is it impossible to give a class literal of a typed array, which's type also expects a type parameter?
You can get the array class from an array instance, for example either one of
arrayOf<Foo<*>>()::class.java
java.lang.reflect.Array.newInstance(Foo::class.java, 0)::class.java
The basic problem: You need to specify the type of your array. This is done using a TypeToken in Gson.
I hope this helps:
val listType = object : TypeToken<Array<String>>() {}.type
val json = """["1"]"""
val yourClassList :Array<String> = Gson().fromJson(json, listType)
print(yourClassList)
Note that for primitives, it is simpler: Gson().fromJson(json, IntArray::class.java)

how to compare arrays in c# without knowing their types

I am having 2 class objects.of same class. It having int string double types of arrays. Where as I need to compare these properties with another object of same class. I need generic approach to compare identical properties regardless of knowing types.

F# - What is array<'T>?

In this previous question I learnt that in F# an array<'T> is not the same as System.Array.
VS tells me that array<'T> inherits System.Array and has the full name Microsoft.FSharp.Core.array<_> and some additional Interfaces.
However MSDN says that array<'T> is a type abbreviation of System.Array. And that it has the notation arr.[i] to get and set items.
So for my lesson, is array<'T> a type abbreviation that includes type extensions and additional Interfaces? Where is the best place to look this up ?
The type array<'T> is an abbreviation, but not for the base type System.Array but for another generic type that represents arrays in F#, which is written as 'T[].
This means that
System.Array is the non-generic base type (where you cannot use indexing and you can only get elements as objects)
'T[] and array<'T> mean exactly the same thing. They are the generic type which supports indexing and you get 'T values from it.

Resources