I have been researching .NET multi dimensional arrays, made by the STATIC method in the Array class - these are called "CreateInstance".
I have attached an image or two to give you an idea of what I was doing when I came across the issue.
The methods of Get Lower/Upper Bounds seem to ignore any settings on the Project regarding "Use Zero Based Arrays". No matter what '__ARRAYBASE__" is set to I get the .NET standard of 0,0,0 and 1,2,3 for my lower and upper bounds.
I have a feeling that the X# compiler may only be handling the cases where arrays are declared using the syntax 'String' and 'INT'. Hopefully 'String[,]' and 'String[,,]' make correctly base 2D and 3D arrays.
Sorry if this causes you some hassle, I don't think one based arrays will ever 'go away' !
it's quit simple: .NET doesn't know anything about /az, __ARRAYBASE__ or things like that.
This is a workaround to use 1-based arrays but only has effect to X# code. Everything inside .NET is 0-based. Everything behind every language is at least 0-based. The first element is always pointer+0. As long as you call .NET methods you will get 0-based results.
The earlier you change your mind to 0-based thinking the less issues you will get. As I said the last days you only confuse yourself when doing tricky things.
0-based thinking is widely used in normal life too. Think about a newly born child. It lives in day zero, week zero, month zero and year zero. After 24 hours we say it is 1 day old, but still zero weeks. It lives in it's year one and we say it is zero years old. And when it turned into it's second year we say it is one year old.
but looking at real code: do you really have code like this? I think in most situations we have loops where it doesn't matter. Or we do what we should do: hide the internal representation. In your example I would have a method like
METHOD GetDayByNumber( number as int ) AS Day
You are missing my point altogether. I am NOT voting for one way or another, in what I posted, but pointing out what looks to me like a "BIG issue" for X#. If there exists a Project property to set Zero Based Arrays to 0/1 for .NET arrays, then it ought to apply to all such arrays, no matter how the X# code or syntax creates the arrays. (I am not talking about VO related arrays.)
I feel that as things are at the moment it is possible to have some .NET arrays operating as one based and others (made from the STATIC methods for CreateInstance) operating as zero based. VERY confusing. This situation needs addressing in my view of things.
Personally Frank, I would go with ZERO based all the way for .NET arrays, and collections like Lists - simply because it seems the safest way forward if we are to embrace .NET. I also would like the default setting for any new X# project to be ZERO based - at the moment is seems as if it is 'one based'.
I don't think logically trying to justify things makes any sense. Birthdays, houses in streets etc., etc.. If you study low level programming it seems that ' 0 ' (zero) is the first unused state of the hardware and/or register / memory, and back in the old days when memory stuff was small / scarce, they tried not to waste resources. I am now trying to think back to 1980 when we programmed the Z80 chip - it was all there - obvious !
For your interest Frank, I always include in my 'ClickStart' eNotes a chapter zero, just to remember good old Don, as he used to try and justify having a zero based syntax ;-0)
I believe FORTRAN is or definitely started with one base. And the Algol 60 I started on could be set by the user / programmer. I often used to use -40 for good scientific reasons, for what I was doing.
So lets at least have X# doing one thing 'fully' by sorting out 'CreateInstance'.
Hope this helps explain things. I am NOT trying to do anything 'fancy' or 'Tricky'. Quite the reverse in fact - I am trying to help explain to Forum guys / user, what is there already.
I am not confusing myself, the confusion is already built into the current compiler it would seem to my research. SORRY Robert, but it was my research findings today
I have to be able to get this stuff straight ready for Cologne and my session on Arrays to Collections.
Fair enough! But, see, you did not use 0-based indexing for when calling the method, you used 1-based, which is the natural thing to do
In my opinion, the only reason for using 0-based arrays/collections etc is absolute speed, saving the last CPU cycle, which made a lot of sense when the c language was invented, but is probably irrelevant nowadays in high level application development. Similar for example for string indexing, it's very counter intuitive using cString:Substr(2) in order to get a substring starting from the 3rd character...
Unfortunately in .Net we are stuck with this design decision by MS, which my guess is that was dictated by the c/c++ guys in the company... But I agree with you, since this is how everything works in .Net, it's probably a good idea to change our mind and always use 0-based indexing, because it will be more consistent. But I really, really hate this
This option does not affect how the assembly being compiled is used from other applications. When the /az option is not used, the compiler generates code to subtract 1 from the array index in order to provide 1-based array indexing semantics at the language level. When the /az option is used, the compiler does not adjust array indexes. Either way, the resulting arrays are always 0-based at the IL level, which allows compatibility with all other .NET languages.
That's all, and that's what I wanted to explain: the X# compiler has no chance to influence the return value of Array.GetLowerBound(). The array itself is always 0-based with all implications.
The easiest way is to follow the .NET way. Accept that if you like it or not.
BTW: Just now I'm working on code based on 2-dim-arrays that I wrote 2007. It was my first code in Vulcan. I want to enhance this code. But what I'm doing now is: I do write unit tests first to be sure nothing happens later. These hours of (for some people meaningless) work will save me much more hours in the future. And let we sleep well!
STATIC METHOD SubStr( SELF s AS STRING, startIndex AS INT ) AS STRING
RETURN s:Substring( startIndex-1, 1 )
STATIC METHOD SubStr( SELF s AS STRING, startIndex AS INT, length AS INT ) AS STRING
RETURN s:Substring( startIndex-1, length )
? "Abc":SubStr(2) // "bc" I hope
? "Abc":SubString(1) // "bc" I hope
? "Abc":SubStr(2,1) // "b" I hope
? "Abc":SubString(1,1) // "b" I hope
you could show us how to avoid issues like you have. You could show us the basic rules:
- avoid magic numbers. Use defines or consts or computed variables instead.
- define a business oriented interface and put the data representation behind, like
method GetDayByNumber( number as int ) as Day
class Days implement IDays
private property _Days as Day
method IDays.GetDayByNumber( number as int ) as Day ; return _Days[number-1]
Later on you can change from array to collection without change any other line of code outside the class definition.
- and of course show the intense use of unit tests to verify it works as intended even after the change to collections.
BTW: you can define an indexed access inside the Days class (and IDays interface of course) by an indexed property where you can do the -1 thing. Look for the special property names 'item' or 'self'. With that you can use Days with the same index syntax as real arrays.
It is all very interesting what you write, however, I have been given a topic by Meinhard, on which I must deliver a session in April 2018 at Cologne.
The session title is "From Arrays to Collections", in which I must have explanatory material on what Arrays and Collections really are and how we can code them in X#.
I can't ignore that fact that a Project setting of 'Use Zero Based Arrays' exists and what impact that then has on our code that we write. Or what happens if the setting get changed further down the development path.
You can actually create and use Arrays without a need to refer to indices at all, but that is not really the point. We have to cover what exists.
Take a look at this image - lines 162 through 166 and see how we can access each and every array element of a three dimensional array without needing to use a single index directly.
The methods used in the lines numbered 147 through 157 are all part of the .NET Framework and are part of the System.Array class. It is the 'Get Bound' methods which seem to be unaware of the Project 0/1 setting.
On a personal note, I try to never use Arrays unless I have no choice, even then there are smarter ways to use them. But we must make sure that what is there works correctly in X# I feel. And that we have a reasonable understanding of how things work.