[Runtime] Adjusted the IMPLICIT Binary <-> BYTE[] operators to use a cloned array for the internal buffer (to make the Binary type truly immutable)

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System
USING System.Text
USING System.Runtime.InteropServices
USING System.Runtime.CompilerServices
USING System.Diagnostics
USING System.Runtime.Serialization
#pragma options ("az", on)
BEGIN NAMESPACE XSharp
    // use explicit layout so we can compact the size into 12 bytes
    // Type is Immutable, so has no settable properties
    /// Internal type that implements the FoxPro Compatible BINARY type.

    /// This type has many operators and implicit converters that normally are never directly called from user code.
    /// The data in this type is stored as an array of Bytes

    /// Conversions from and to String are supported and they use the current active windows codepage.
    ///
    [Serializable];
    PUBLIC STRUCTURE __Binary IMPLEMENTS IFormattable, ;
        IComparable<__Binary>, ;
        IEquatable<__Binary>, ;
        IComparable,           ;
        ISerializable

        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PRIVATE INITONLY _value AS BYTE[]

        #region constructors
        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        /// <param name="b">Byte[] value that has the bytes that define the binary</param>
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (b AS BYTE[])
            IF b == NULL
                THROW NullError()
            ENDIF
            SELF:_value    := b

        PRIVATE STATIC METHOD NullError() AS Error
            VAR err			 := Error{ArgumentException{}}
            err:Gencode		 := Gencode.EG_ARG
            err:ArgNum		 := 1
            err:FuncSym		 := "Binary.ctor"
            err:Description  := "Argument cannot be null"
            err:Args         := <OBJECT> {NULL}
            RETURN err

        PRIVATE CONSTRUCTOR( lhs AS BYTE[], rhs AS BYTE[])
            VAR len := lhs:Length + rhs:Length
            VAR result := BYTE[]{len}
            System.Array.Copy(lhs, result, lhs:Length)
            System.Array.Copy(rhs, 0, result,lhs:Length, rhs:Length)
            _value := result

        #endregion
        #region Properties
        /// Binary value as array of Bytes
        PROPERTY @@Value    AS BYTE[]	GET _value
        PROPERTY Length     AS LONG GET iif(_value == NULL, 0, _value:Length)
        #endregion

        #region Equality Operators
        /// <inheritdoc />
        OVERRIDE METHOD Equals(rhs AS OBJECT  ) AS LOGIC
            LOCAL result AS LOGIC
            IF rhs != NULL .AND. rhs IS __Binary
                result := SELF:Equals( (__Binary) rhs)
            ELSE
                result := FALSE
            ENDIF
            RETURN result

        /// <inheritdoc />
        METHOD Equals(rhs AS __Binary ) AS LOGIC
            IF SELF:Length != rhs:Length
                RETURN FALSE
            ENDIF
            FOR VAR i := 0 TO SELF:Length-1
                IF SELF:Value[i] != rhs:Value[i]
                    RETURN FALSE
                ENDIF
            NEXT
            RETURN TRUE

            /// <inheritdoc />
        OVERRIDE METHOD GetHashCode() AS INT
            RETURN SELF:_value:GetHashCode()

            /// <exclude />
        METHOD GetTypeCode() AS TypeCode
            RETURN TypeCode.Object

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR ==(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            RETURN lhs:Equals(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR !=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            RETURN ! lhs:Equals(rhs)
            #endregion

        #region Comparison Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR >(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            VAR len := Math.Min(lhs:Length,rhs:Length)
            VAR res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            IF res > 0
                RETURN TRUE
            ELSEIF res < 0
                RETURN FALSE
            ENDIF
            RETURN lhs:Length > rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR <(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            VAR len := Math.Min(lhs:Length,rhs:Length)
            VAR res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            IF res < 0
                RETURN TRUE
            ELSEIF res > 0
                RETURN FALSE
            ENDIF
            RETURN lhs:Length < rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR >=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            VAR len := Math.Min(lhs:Length,rhs:Length)
            VAR res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            IF res > 0
                RETURN TRUE
            ELSEIF res < 0
                RETURN FALSE
            ENDIF
            RETURN lhs:Length >= rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR <=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            VAR len := Math.Min(lhs:Length,rhs:Length)
            VAR res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            IF res < 0
                RETURN TRUE
            ELSEIF res > 0
                RETURN FALSE
            ENDIF
            RETURN lhs:Length <= rhs:Length

            #endregion

        #region Implicit Converters
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS BYTE[]) AS __Binary
            RETURN __Binary{(BYTE[])b:Clone()}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS __Binary) AS BYTE[]
            RETURN (BYTE[])b:Value:Clone()

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(bytes AS __Binary) AS STRING
            RETURN RuntimeState.WinEncoding:GetString(bytes:Value)

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(s AS STRING) AS __Binary
            RETURN __Binary{ RuntimeState.WinEncoding:GetBytes(s) }

            #endregion

        #region Numeric Operators

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR+(lhs AS __Binary, rhs AS __Binary) AS __Binary
            RETURN __Binary{lhs:Value, rhs:Value}

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR+(lhs AS __Binary, rhs AS STRING) AS __Binary
            RETURN __Binary{lhs:Value, RuntimeState.WinEncoding:GetBytes(rhs)}

        OPERATOR+(lhs AS STRING, rhs AS __Binary) AS STRING
            VAR sb := StringBuilder{}
            sb:Append(lhs)
            sb:Append(RuntimeState.WinEncoding:GetString(rhs))
            RETURN sb:ToString()

        #endregion
        #region Unary Operators

            #endregion
        #region Add and Subtract
        /// <exclude />
        METHOD Add(rhs AS __Binary) AS __Binary
            RETURN SELF + rhs

        /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS __Binary) AS INT
            VAR len := Math.Min(SELF:Length,rhs:Length)
            FOR VAR i := 0 TO len-1
                IF SELF:Value[i] > rhs:Value[i]
                    RETURN 1
                ELSEIF SELF:Value[i] < rhs:Value[i]
                    RETURN -1
                ENDIF
            NEXT
            IF SELF:Length > rhs:Length
                RETURN 1
            ELSEIF SELF:Length < rhs:Length
                RETURN -1
            ENDIF
            RETURN 0
            /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS OBJECT) AS INT
            RETURN SELF:CompareTo( (__Binary) rhs)
            #endregion

        #region IFormattable
        /// <inheritdoc />
        PUBLIC OVERRIDE METHOD ToString() AS STRING
            RETURN SELF:ToString("")

        /// <inheritdoc cref="System.Double.ToString"/>
        PUBLIC METHOD ToString(sFormat AS STRING) AS STRING
            IF sFormat == "G"
                RETURN RuntimeState:WinEncoding:GetString(SELF:Value)
            ENDIF
            VAR sb := StringBuilder{}
            sb:Append("0h")
            FOREACH VAR b IN SELF:Value
                sb:Append(b:ToString("X2"))
            NEXT
            RETURN sb:ToString()
            /// <inheritdoc />
        PUBLIC METHOD ToString(format AS STRING, provider AS System.IFormatProvider) AS STRING
            RETURN SELF:ToString(format)
            #endregion
        #region ISerializable
        /// <inheritdoc/>

        PUBLIC METHOD GetObjectData(info AS SerializationInfo, context AS StreamingContext) AS VOID
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            info:AddValue("Value", SELF:ToString(""))
            RETURN
        /// <include file="RTComments.xml" path="Comments/SerializeConstructor/*" />
        CONSTRUCTOR (info AS SerializationInfo, context AS StreamingContext)
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            _value := NULL
            VAR s := info:GetString("Value")
            IF s:ToLower():StartsWith("0h")
                _value := BYTE[]{(s:Length -2)/2} // subtract 2 for 0h
                LOCAL current := 0 AS INT
                FOR VAR i := 2 TO s:Length-1 STEP 2
                    VAR nibble := s:Substring(i,2)
                    _value[current] := Val("0x"+nibble)
                    current += 1
                NEXT
            ENDIF
        #endregion
        /*
        #region IConvertible
			// forward most methods to the DateTime class so there will
			// be a proper (localized) error message
			/// <inheritdoc />
			METHOD IConvertible.ToBoolean(provider AS System.IFormatProvider) AS LOGIC
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToByte(provider AS System.IFormatProvider) AS BYTE
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToChar(provider AS System.IFormatProvider) AS CHAR
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDateTime(provider AS System.IFormatProvider) AS System.DateTime
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDecimal(provider AS System.IFormatProvider) AS DECIMAL
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDouble(provider AS System.IFormatProvider) AS REAL8
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt16(provider AS System.IFormatProvider) AS SHORT
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt32(provider AS System.IFormatProvider) AS LONG
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt64(provider AS System.IFormatProvider) AS INT64
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToSByte(provider AS System.IFormatProvider) AS SByte
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToSingle(provider AS System.IFormatProvider) AS REAL4
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt16(provider AS System.IFormatProvider) AS WORD
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt32(provider AS System.IFormatProvider) AS DWORD
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt64(provider AS System.IFormatProvider) AS UINT64
				THROW NotImplementedException{}

            METHOD IConvertible.ToType(conversionType AS System.Type, provider AS System.IFormatProvider) AS OBJECT
				IF conversionType == TYPEOF(STRING)
					RETURN SELF:ToString("")
				ENDIF
				THROW NotImplementedException{}

		    METHOD IConvertible.ToString(provider AS System.IFormatProvider) AS STRING
			    RETURN SELF:ToString("")

        #endregion
        */
    END STRUCTURE

END NAMESPACE

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System
USING System.Text
USING System.Runtime.InteropServices
USING System.Runtime.CompilerServices
USING System.Diagnostics
USING System.Runtime.Serialization
#pragma options ("az", on)
BEGIN NAMESPACE XSharp
    // use explicit layout so we can compact the size into 12 bytes
    // Type is Immutable, so has no settable properties
    /// Internal type that implements the FoxPro Compatible BINARY type.

    /// This type has many operators and implicit converters that normally are never directly called from user code.
    /// The data in this type is stored as an array of Bytes

    /// Conversions from and to String are supported and they use the current active windows codepage.
    ///
    [Serializable];
    PUBLIC STRUCTURE __Binary IMPLEMENTS IFormattable, ;
        IComparable<__Binary>, ;
        IEquatable<__Binary>, ;
        IComparable,           ;
        ISerializable

        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PRIVATE INITONLY _value AS BYTE[]

        #region constructors
        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        /// <param name="b">Byte[] value that has the bytes that define the binary</param>
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (b as Byte[])
            IF b == NULL
                THROW NullError()
            ENDIF
            SELF:_value    := b

        PRIVATE STATIC METHOD NullError() as Error
            VAR err			 := Error{ArgumentException{}}
            err:Gencode		 := Gencode.EG_ARG
            err:ArgNum		 := 1
            err:FuncSym		 := "Binary.ctor"
            err:Description  := "Argument cannot be null"
            err:Args         := <OBJECT> {NULL}
            return err

        PRIVATE CONSTRUCTOR( lhs as byte[], rhs as byte[])
            var len := lhs:Length + rhs:Length
            var result := byte[]{len}
            System.Array.Copy(lhs, result, lhs:Length)
            System.Array.Copy(rhs, 0, result,lhs:Length, rhs:Length)
            _value := result

        #endregion
        #region Properties
        /// Binary value as array of Bytes
        PROPERTY @@Value    AS Byte[]	GET _value
        PROPERTY Length     AS LONG GET iif(_value == NULL, 0, _value:Length)
        #endregion

        #region Equality Operators
        /// <inheritdoc />
        OVERRIDE METHOD Equals(rhs AS OBJECT  ) AS LOGIC
            LOCAL result AS LOGIC
            IF rhs != NULL .AND. rhs IS __Binary
                result := SELF:Equals( (__Binary) rhs)
            ELSE
                result := FALSE
            ENDIF
            RETURN result

        /// <inheritdoc />
        METHOD Equals(rhs AS __Binary ) AS LOGIC
            IF SELF:Length != rhs:Length
                RETURN FALSE
            ENDIF
            FOR VAR i := 0 to SELF:Length-1
                IF SELF:Value[i] != rhs:Value[i]
                    RETURN FALSE
                ENDIF
            NEXT
            RETURN TRUE

            /// <inheritdoc />
        OVERRIDE METHOD GetHashCode() AS INT
            RETURN SELF:_value:GetHashCode()

            /// <exclude />
        METHOD GetTypeCode() AS TypeCode
            RETURN TypeCode.Object

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR ==(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            RETURN lhs:Equals(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR !=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            RETURN ! lhs:Equals(rhs)
            #endregion

        #region Comparison Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR >(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            var len := Math.Min(lhs:Length,rhs:Length)
            var res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            if res > 0
                return TRUE
            elseif res < 0
                return FALSE
            endif
            RETURN lhs:Length > rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR <(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            var len := Math.Min(lhs:Length,rhs:Length)
            var res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            if res < 0
                return TRUE
            elseif res > 0
                return FALSE
            endif
            RETURN lhs:Length < rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR >=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            var len := Math.Min(lhs:Length,rhs:Length)
            var res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            if res > 0
                return TRUE
            elseif res < 0
                return FALSE
            endif
            RETURN lhs:Length >= rhs:Length

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR <=(lhs AS __Binary, rhs AS __Binary) AS LOGIC
            var len := Math.Min(lhs:Length,rhs:Length)
            var res := RuntimeState.StringCompare(lhs:Value, rhs:Value, len)
            if res < 0
                return TRUE
            elseif res > 0
                return FALSE
            endif
            RETURN lhs:Length <= rhs:Length

            #endregion

        #region Implicit Converters
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS BYTE[]) AS __Binary
            RETURN __Binary{b}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS __Binary) AS BYTE[]
            RETURN b:Value

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(bytes AS __Binary) AS STRING
            RETURN RuntimeState.WinEncoding:GetString(bytes:Value)

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(s AS STRING) AS __Binary
            RETURN __Binary{ RuntimeState.WinEncoding:GetBytes(s) }

            #endregion

        #region Numeric Operators

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR+(lhs AS __Binary, rhs AS __Binary) AS __Binary
            return __Binary{lhs:Value, rhs:Value}

        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        OPERATOR+(lhs AS __Binary, rhs AS STRING) AS __Binary
            return __Binary{lhs:Value, RuntimeState.WinEncoding:GetBytes(rhs)}

        OPERATOR+(lhs AS STRING, rhs AS __Binary) AS STRING
            var sb := StringBuilder{}
            sb:Append(lhs)
            sb:Append(RuntimeState.WinEncoding:GetString(rhs))
            RETURN sb:ToString()

        #endregion
        #region Unary Operators

            #endregion
        #region Add and Subtract
        /// <exclude />
        METHOD Add(rhs AS __Binary) AS __Binary
            RETURN SELF + rhs

        /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS __Binary) AS INT
            var len := Math.Min(SELF:Length,rhs:Length)
            for var i := 0 to len-1
                if SELF:Value[i] > rhs:Value[i]
                    return 1
                ELSEIF SELF:Value[i] < rhs:Value[i]
                    return -1
                ENDIF
            next
            if SELF:Length > rhs:Length
                RETURN 1
            ELSEIF SELF:Length < rhs:Length
                return -1
            ENDIF
            RETURN 0
            /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS OBJECT) AS INT
            RETURN SELF:CompareTo( (__Binary) rhs)
            #endregion

        #region IFormattable
        /// <inheritdoc />
        PUBLIC OVERRIDE METHOD ToString() AS STRING
            RETURN SELF:ToString("")

        /// <inheritdoc cref="System.Double.ToString"/>
        PUBLIC METHOD ToString(sFormat AS STRING) AS STRING
            if sFormat == "G"
                return RuntimeState:WinEncoding:GetString(self:Value)
            endif
            var sb := StringBuilder{}
            sb:Append("0h")
            foreach var b in self:Value
                sb:Append(b:ToString("X2"))
            next
            return sb:ToString()
            /// <inheritdoc />
        PUBLIC METHOD ToString(format AS STRING, provider AS System.IFormatProvider) AS STRING
            RETURN SELF:ToString(format)
            #endregion
        #region ISerializable
        /// <inheritdoc/>

        PUBLIC METHOD GetObjectData(info AS SerializationInfo, context AS StreamingContext) AS VOID
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            info:AddValue("Value", SELF:ToString(""))
            RETURN
        /// <include file="RTComments.xml" path="Comments/SerializeConstructor/*" />
        CONSTRUCTOR (info AS SerializationInfo, context AS StreamingContext)
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            _value := NULL
            VAR s := info:GetString("Value")
            IF s:ToLower():StartsWith("0h")
                _value := BYTE[]{(s:Length -2)/2} // subtract 2 for 0h
                LOCAL current := 0 AS INT
                FOR VAR i := 2 TO s:Length-1 STEP 2
                    VAR nibble := s:Substring(i,2)
                    _value[current] := Val("0x"+nibble)
                    current += 1
                NEXT
            ENDIF
        #endregion
        /*
        #region IConvertible
			// forward most methods to the DateTime class so there will
			// be a proper (localized) error message
			/// <inheritdoc />
			METHOD IConvertible.ToBoolean(provider AS System.IFormatProvider) AS LOGIC
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToByte(provider AS System.IFormatProvider) AS BYTE
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToChar(provider AS System.IFormatProvider) AS CHAR
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDateTime(provider AS System.IFormatProvider) AS System.DateTime
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDecimal(provider AS System.IFormatProvider) AS DECIMAL
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToDouble(provider AS System.IFormatProvider) AS REAL8
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt16(provider AS System.IFormatProvider) AS SHORT
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt32(provider AS System.IFormatProvider) AS LONG
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToInt64(provider AS System.IFormatProvider) AS INT64
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToSByte(provider AS System.IFormatProvider) AS SByte
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToSingle(provider AS System.IFormatProvider) AS REAL4
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt16(provider AS System.IFormatProvider) AS WORD
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt32(provider AS System.IFormatProvider) AS DWORD
				THROW NotImplementedException{}

			/// <inheritdoc />
			METHOD IConvertible.ToUInt64(provider AS System.IFormatProvider) AS UINT64
				THROW NotImplementedException{}

            METHOD IConvertible.ToType(conversionType AS System.Type, provider AS System.IFormatProvider) AS OBJECT
				IF conversionType == TYPEOF(STRING)
					RETURN SELF:ToString("")
				ENDIF
				THROW NotImplementedException{}

		    METHOD IConvertible.ToString(provider AS System.IFormatProvider) AS STRING
			    RETURN SELF:ToString("")

        #endregion
        */
    END STRUCTURE

END NAMESPACE


[Runtime] DbUnLock() now also accepts a record number

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

USING XSharp
USING XSharp.RDD
USING XSharp.RDD.Enums
USING System.Collections.Generic
USING System.IO
USING System.Reflection
USING System.Linq
USING System.Text

/// <exclude />
FUNCTION _DbThrowErrorOnFailure(funcName AS STRING, resultToCheck AS LOGIC) AS LOGIC
    IF !resultToCheck
        resultToCheck := (LOGIC) DoError(funcName)
    ENDIF
    RETURN resultToCheck

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/alias0/*" />
FUNCTION Alias0() AS STRING
   LOCAL oRDD := VoDb.CWA("Alias0", FALSE) AS IRDD
    IF oRDD != NULL
        RETURN oRDD:Alias
    ENDIF
    RETURN String.Empty

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/bof/*" />
FUNCTION Bof() AS LOGIC
   RETURN VoDb.Bof()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbf/*" />
FUNCTION DBF() AS STRING
    RETURN VoDb.DBF()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbpack/*" />
FUNCTION DbPack() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Pack())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbrecall/*" />
FUNCTION DbRecall() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Recall())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbunlock/*" />
FUNCTION DbUnLock(nRecord) AS LOGIC
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Unlock(nRecord))

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbzap/*" />
FUNCTION DbZap() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Zap())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbunlockall/*" />
FUNCTION DbUnlockAll() AS LOGIC STRICT
	RETURN VoDb.UnlockAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/deleted/*" />
FUNCTION Deleted() AS LOGIC STRICT
	RETURN VoDb.Deleted()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/eof/*" />
FUNCTION Eof() AS LOGIC
   RETURN VoDb.Eof()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/flock/*" />
FUNCTION Flock() AS LOGIC STRICT
	RETURN VoDb.Flock()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fcount/*" />
FUNCTION FCount() AS DWORD
    RETURN VoDb.FCount()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldname/*" />
FUNCTION FieldName(dwFieldPos AS DWORD) AS STRING
    IF dwFieldPos > 0 .AND. dwFieldPos <= VoDb.FCount()
        RETURN VoDb.FieldName(dwFieldPos)
    ENDIF
    RETURN String.Empty

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldsym/*" />
FUNCTION FieldSym(dwFieldPos AS DWORD) AS SYMBOL
    IF dwFieldPos > 0 .AND. dwFieldPos <= VoDb.FCount()
        RETURN (SYMBOL) VoDb.FieldName(dwFieldPos)
    ENDIF
    RETURN NULL_SYMBOL

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldpos/*" />
FUNCTION FieldPos(cFieldName AS STRING) AS DWORD
    RETURN VoDb.FieldPos(cFieldName)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldpos/*" />
FUNCTION FieldPos(cFieldName AS STRING, nArea AS DWORD) AS DWORD
    LOCAL oRDD := RuntimeState.WorkAreas:GetRDD(nArea) AS IRDD
    IF oRDD != NULL_OBJECT
        RETURN (DWORD) oRDD:FieldIndex(cFieldName)
    ENDIF
    RETURN 0

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/found/*" />
FUNCTION Found() AS LOGIC
	RETURN VoDb.Found()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/header/*" />
FUNCTION Header() AS LONG
    LOCAL oValue := NULL AS OBJECT
	VoDb.Info(DBI_GETHEADERSIZE, REF oValue)
    RETURN (LONG) oValue

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/lastrec/*" />
FUNCTION LastRec() AS DWORD
    RETURN (DWORD) VoDb.LastRec()

/// <summary>
/// </summary>
/// <returns>
/// </returns>
FUNCTION DbBuffRefresh() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.BuffRefresh())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclearfilter/*" />
FUNCTION DbClearFilter() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.ClearFilter())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclearrelation/*" />
FUNCTION DbClearRelation() AS LOGIC STRICT
	RETURN VoDb.ClearRelation()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcloseall/*" />
FUNCTION DbCloseAll() AS LOGIC STRICT
	RETURN VoDb.CloseAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclosearea/*" />
FUNCTION DbCloseArea () AS LOGIC STRICT
	RETURN VoDb.CloseArea()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcommit/*" />
FUNCTION DbCommit() AS LOGIC STRICT
	RETURN VoDb.Commit()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcommitall/*" />
FUNCTION DbCommitAll() AS LOGIC STRICT
	RETURN VoDb.CommitAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcontinue/*" />
FUNCTION DbContinue() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Continue())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbdriver/*" />
FUNCTION DbDriver() AS STRING STRICT
	RETURN RddName()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbfilter/*" />
FUNCTION DbFilter() AS STRING STRICT
	RETURN VoDb.Filter()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgetselect/*" />
FUNCTION DbGetSelect() AS DWORD STRICT
	RETURN VoDb.GetSelect()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgobottom/*" />
FUNCTION DbGoBottom() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.GoBottom())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgotop/*" />
FUNCTION DbGoTop() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.GoTop())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddname/*" />
FUNCTION RddName        () AS STRING STRICT
	LOCAL cRet      AS STRING
	IF Used()
		cRet := VoDb.RddName()
	ELSE
		cRet := RddSetDefault()
	ENDIF
	RETURN cRet

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddsetdefault/*" />
FUNCTION RddSetDefault  () AS STRING STRICT
    RETURN VoDb.RddSetDefault(NULL_STRING)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddsetdefault/*" />
FUNCTION RddSetDefault  (cNewSetting AS STRING) AS STRING
    RETURN VoDb.RddSetDefault(cNewSetting)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/reccount/*" />
FUNCTION RecCount() AS LONG
    RETURN VoDb.LastRec()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/recno/*" />
FUNCTION RecNo() AS DWORD
    RETURN VoDb.Recno()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/recsize/*" />
FUNCTION RecSize AS LONG
    RETURN VoDb.RecSize()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rlock/*" />
FUNCTION RLock() AS LOGIC STRICT
	RETURN VoDb.Rlock(NULL)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/used/*" />
FUNCTION Used() AS LOGIC
    RETURN RuntimeState.Workareas:CurrentWorkArea != NULL

FUNCTION DoError (cSymFunc AS STRING, nTries:= 0 AS INT) AS OBJECT
	LOCAL oError    AS Error
    LOCAL bBlock    AS ICodeblock
    IF RuntimeState.LastRDDError IS Error
	    oError         := (Error) RuntimeState.LastRDDError
    ELSEIF RuntimeState.LastRDDError != NULL_OBJECT
        oError         := Error{RuntimeState.LastRDDError}
    ELSE
        oError  := Error{"Unknown Error occurred" }
    ENDIF
	oError:FuncSym := cSymFunc
    oError:Tries   := nTries
    bBlock := XSharp.RuntimeState.GetValue<ICodeblock>(Set.ErrorBlock)
    IF bBlock != NULL
	    RETURN bBlock:EvalBlock(oError)
    ENDIF
    THROW oError

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//

USING XSharp
USING XSharp.RDD
USING XSharp.RDD.Enums
USING System.Collections.Generic
USING System.IO
USING System.Reflection
USING System.Linq
USING System.Text

/// <exclude />
FUNCTION _DbThrowErrorOnFailure(funcName AS STRING, resultToCheck AS LOGIC) AS LOGIC
    IF !resultToCheck
        resultToCheck := (LOGIC) DoError(funcName)
    ENDIF
    RETURN resultToCheck

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/alias0/*" />
FUNCTION Alias0() AS STRING
   LOCAL oRDD := VoDb.CWA("Alias0", FALSE) AS IRDD
    IF oRDD != NULL
        RETURN oRDD:Alias
    ENDIF
    RETURN String.Empty

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/bof/*" />
FUNCTION Bof() AS LOGIC
   RETURN VoDb.Bof()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbf/*" />
FUNCTION DBF() AS STRING
    RETURN VoDb.DBF()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbpack/*" />
FUNCTION DbPack() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Pack())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbrecall/*" />
FUNCTION DbRecall() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Recall())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbunlock/*" />
FUNCTION DbUnLock() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Unlock(NULL_OBJECT))

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbzap/*" />
FUNCTION DbZap() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Zap())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbunlockall/*" />
FUNCTION DbUnlockAll() AS LOGIC STRICT
	RETURN VoDb.UnlockAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/deleted/*" />
FUNCTION Deleted() AS LOGIC STRICT
	RETURN VoDb.Deleted()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/eof/*" />
FUNCTION Eof() AS LOGIC
   RETURN VoDb.Eof()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/flock/*" />
FUNCTION Flock() AS LOGIC STRICT
	RETURN VoDb.Flock()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fcount/*" />
FUNCTION FCount() AS DWORD
    RETURN VoDb.FCount()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldname/*" />
FUNCTION FieldName(dwFieldPos AS DWORD) AS STRING
    IF dwFieldPos > 0 .AND. dwFieldPos <= VoDb.FCount()
        RETURN VoDb.FieldName(dwFieldPos)
    ENDIF
    RETURN String.Empty

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldsym/*" />
FUNCTION FieldSym(dwFieldPos AS DWORD) AS SYMBOL
    IF dwFieldPos > 0 .AND. dwFieldPos <= VoDb.FCount()
        RETURN (SYMBOL) VoDb.FieldName(dwFieldPos)
    ENDIF
    RETURN NULL_SYMBOL

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldpos/*" />
FUNCTION FieldPos(cFieldName AS STRING) AS DWORD
    RETURN VoDb.FieldPos(cFieldName)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/fieldpos/*" />
FUNCTION FieldPos(cFieldName AS STRING, nArea AS DWORD) AS DWORD
    LOCAL oRDD := RuntimeState.WorkAreas:GetRDD(nArea) AS IRDD
    IF oRDD != NULL_OBJECT
        RETURN (DWORD) oRDD:FieldIndex(cFieldName)
    ENDIF
    RETURN 0

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/found/*" />
FUNCTION Found() AS LOGIC
	RETURN VoDb.Found()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/header/*" />
FUNCTION Header() AS LONG
    LOCAL oValue := NULL AS OBJECT
	VoDb.Info(DBI_GETHEADERSIZE, REF oValue)
    RETURN (LONG) oValue

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/lastrec/*" />
FUNCTION LastRec() AS DWORD
    RETURN (DWORD) VoDb.LastRec()

/// <summary>
/// </summary>
/// <returns>
/// </returns>
FUNCTION DbBuffRefresh() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.BuffRefresh())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclearfilter/*" />
FUNCTION DbClearFilter() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.ClearFilter())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclearrelation/*" />
FUNCTION DbClearRelation() AS LOGIC STRICT
	RETURN VoDb.ClearRelation()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcloseall/*" />
FUNCTION DbCloseAll() AS LOGIC STRICT
	RETURN VoDb.CloseAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbclosearea/*" />
FUNCTION DbCloseArea () AS LOGIC STRICT
	RETURN VoDb.CloseArea()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcommit/*" />
FUNCTION DbCommit() AS LOGIC STRICT
	RETURN VoDb.Commit()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcommitall/*" />
FUNCTION DbCommitAll() AS LOGIC STRICT
	RETURN VoDb.CommitAll()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbcontinue/*" />
FUNCTION DbContinue() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.Continue())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbdriver/*" />
FUNCTION DbDriver() AS STRING STRICT
	RETURN RddName()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbfilter/*" />
FUNCTION DbFilter() AS STRING STRICT
	RETURN VoDb.Filter()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgetselect/*" />
FUNCTION DbGetSelect() AS DWORD STRICT
	RETURN VoDb.GetSelect()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgobottom/*" />
FUNCTION DbGoBottom() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.GoBottom())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/dbgotop/*" />
FUNCTION DbGoTop() AS LOGIC STRICT
	RETURN _DbThrowErrorOnFailure(__FUNCTION__, VoDb.GoTop())

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddname/*" />
FUNCTION RddName        () AS STRING STRICT
	LOCAL cRet      AS STRING
	IF Used()
		cRet := VoDb.RddName()
	ELSE
		cRet := RddSetDefault()
	ENDIF
	RETURN cRet

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddsetdefault/*" />
FUNCTION RddSetDefault  () AS STRING STRICT
    RETURN VoDb.RddSetDefault(NULL_STRING)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rddsetdefault/*" />
FUNCTION RddSetDefault  (cNewSetting AS STRING) AS STRING
    RETURN VoDb.RddSetDefault(cNewSetting)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/reccount/*" />
FUNCTION RecCount() AS LONG
    RETURN VoDb.LastRec()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/recno/*" />
FUNCTION RecNo() AS DWORD
    RETURN VoDb.Recno()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/recsize/*" />
FUNCTION RecSize AS LONG
    RETURN VoDb.RecSize()

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/rlock/*" />
FUNCTION RLock() AS LOGIC STRICT
	RETURN VoDb.Rlock(NULL)

/// <include file="VoFunctionDocs.xml" path="Runtimefunctions/used/*" />
FUNCTION Used() AS LOGIC
    RETURN RuntimeState.Workareas:CurrentWorkArea != NULL

FUNCTION DoError (cSymFunc AS STRING, nTries:= 0 AS INT) AS OBJECT
	LOCAL oError    AS Error
    LOCAL bBlock    AS ICodeblock
    IF RuntimeState.LastRDDError IS Error
	    oError         := (Error) RuntimeState.LastRDDError
    ELSEIF RuntimeState.LastRDDError != NULL_OBJECT
        oError         := Error{RuntimeState.LastRDDError}
    ELSE
        oError  := Error{"Unknown Error occurred" }
    ENDIF
	oError:FuncSym := cSymFunc
    oError:Tries   := nTries
    bBlock := XSharp.RuntimeState.GetValue<ICodeblock>(Set.ErrorBlock)
    IF bBlock != NULL
	    RETURN bBlock:EvalBlock(oError)
    ENDIF
    THROW oError


[Runtime] Fixes #138

[Runtime] Fixes #138

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System.Collections
USING System.Collections.Generic
USING System.Linq
USING System.Diagnostics
USING System.Reflection
USING XSharp
BEGIN NAMESPACE XSharp
	/// Internal type that implements the new TYPED ARRAY type.

	/// This type has methods and properties that normally are never directly called from user code.
	///
	PUBLIC CLASS __ArrayBase<T> IMPLEMENTS INamedIndexer, IEnumerable<T> WHERE T IS NEW()
		INTERNAL _internalList AS List<T>
		PRIVATE _islocked AS LOGIC
		#region constructors
		/// Create an empty array
		CONSTRUCTOR()
			_internalList := List<T>{}
			RETURN

		/// Create an array with a certain number of elements. Each element will be filled with a default value.
		CONSTRUCTOR(capacity AS DWORD)
			_internalList := List<T>{ (INT) capacity}
			//_internalList:AddRange(Enumerable.Repeat(DEFAULT(T),(INT) capacity))
			RETURN

		/// Create an array and fill it with elements from an existing collection.
		CONSTRUCTOR( collection AS IEnumerable<T>)
			_internalList := List<T>{collection}
			RETURN

		/// Create an array and fill it with elements from an existing .Net array of objects. Note that the objects must be of the right type.
		CONSTRUCTOR( elements AS OBJECT[] )
			SELF()
			IF elements == NULL
				THROW ArgumentNullException{NAMEOF(elements)}
			ENDIF
			FOREACH element AS OBJECT IN elements
				IF element == NULL
					_internalList:add(DEFAULT(T))
				ELSEIF element IS T
					_internalList:Add( (T) element)
				ELSE
					THROW ArgumentException{"Object array contains element of incorrect type "+element:GetType():FullName}
				ENDIF
			NEXT
			RETURN

		/// Create an array and fill it with elements from an existing .Net array.
		CONSTRUCTOR( elements AS T[] )
			_internalList := List<T>{elements}
			RETURN
			#endregion

		#region properties
		/// Is the array empty.
		PUBLIC PROPERTY IsEmpty AS LOGIC GET _internalList:Count == 0
		/// Length of the array.
		PUBLIC PROPERTY Length AS DWORD GET (DWORD) _internalList:Count
        /// Length of the array as integer.
        PUBLIC PROPERTY Count AS INT GET _internalList:Count
		#endregion

		#region Enumerators
		PUBLIC METHOD IEnumerable<T>.GetEnumerator() AS IEnumerator<T>
			RETURN _internalList:GetEnumerator()

		PUBLIC METHOD IEnumerable.GetEnumerator() AS IEnumerator
			RETURN _internalList:GetEnumerator()

			#endregion

		#region Cloning

		INTERNAL METHOD Clone() AS __ArrayBase<T>
			LOCAL aResult AS __ArrayBase<T>
			LOCAL nCount AS DWORD
			nCount := (DWORD) _internalList:Count
			aResult := (__ArrayBase<T>) Activator.CreateInstance(SELF:GetType(), NULL)
			aResult:Resize( _internalList:Count )
		    // warning, nCount-1 below will become MAXDWORD for nCount == 0
			IF nCount == 0
				RETURN aResult
            ENDIF
			FOR VAR I := 0 TO nCount-1
				aResult:_internalList[i] := _internalList[i]
			NEXT
			RETURN aResult

			#endregion

		#region Indexers and TO GET / SET Elements.
	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The element stored at the specified location in the array.</returns>
        PUBLIC METHOD __GetElement(index AS INT) AS T
			RETURN SELF:_internalList[ index ]

	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name='e'>New element to store in the array at the position specified</param>
        /// <returns>The new element</returns>
		PUBLIC METHOD __SetElement(e AS T,index AS INT) AS T
			IF SELF:CheckLock()
				_internalList[index]:=e
			ENDIF
			RETURN e

		PRIVATE METHOD __GetProperty(sName AS STRING) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL oProp AS PropertyInfo
			type := TYPEOF(T)
			oProp := type:GetProperty(sName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
			IF oProp == NULL_OBJECT
				THROW ArgumentException{"Unknown property: "+sName}
			ENDIF
			RETURN oProp

		PRIVATE METHOD __GetIndexer(lNumeric AS LOGIC) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL aProps AS PropertyInfo[]
			type := TYPEOF(T)
			aProps := type:GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
            FOREACH oProp AS PropertyInfo IN aProps
                IF !oProp:Name:Tolower() == "item"
                    LOOP
                ENDIF
                LOCAL pars := oProp:GetIndexParameters() AS ParameterInfo[]
                IF pars:Length > 0
                    LOCAL par := pars[__ARRAYBASE__] AS ParameterInfo
                    SWITCH Type.GetTypeCode(par:ParameterType)
                    CASE TypeCode.Int32
                    CASE TypeCode.Int64
                    CASE TypeCode.UInt32
                    CASE TypeCode.UInt64
                        IF (lNumeric)
                            RETURN oProp
                        ENDIF
                    CASE TypeCode.String
                        IF (!lNumeric)
                            RETURN oProp
                        ENDIF
                    END SWITCH
                ENDIF

            NEXT
			RETURN NULL

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
		/// <returns>The element stored at the indicated location in the collection.</returns>
		PUBLIC PROPERTY SELF[index AS INT] AS T
			GET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				RETURN _internalList[index ]
			END GET
			SET
				IF SELF:CheckLock()
					IF index > _internalList:Count-1
						THROW ArgumentOutOfRangeException{}
					ENDIF
					_internalList[index] := VALUE
				ENDIF
			END SET
		END PROPERTY

        /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
        /// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="index2"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, index2 AS INT] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[index2]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(TRUE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{index2})
                ENDIF
                THROW ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[index2] := VALUE
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(TRUE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(VALUE, oProp:PropertyType), <OBJECT>{index2} )
                        RETURN
                    ENDIF
                    THROW ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}
				ENDIF
			END SET
		END PROPERTY

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="name"><include file="RTComments.xml" path="Comments/NameBasedIndexParam/*" /></param>
		/// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, name AS STRING] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[name]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(FALSE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{name})
                ENDIF
				oProp	 := __GetProperty( name)
				RETURN oProp:GetValue(oElement, NULL)
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[name] := VALUE
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(FALSE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(VALUE, oProp:PropertyType), <OBJECT>{name} )
                        RETURN
                    ENDIF
					oProp	 := __GetProperty( name)
					oProp:SetValue(oElement, NULL, VALUE)
				ENDIF
			END SET
		END PROPERTY

		#endregion

		#region Insert and Delete elements
        /// <exclude />
		PUBLIC METHOD Add(u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:Add(u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Delete(position AS INT) AS __ArrayBase<T>
			SELF:RemoveAt(position)
			SELF:Add(T{})
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD Insert(index AS INT,u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveAt(_internalList:Count - 1)
				_internalList:Insert((INT) index-__ARRAYBASE__ ,u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Insert(position AS INT) AS __ArrayBase<T>
			SELF:Insert( position, DEFAULT(T))
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD RemoveAt(index AS INT) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveRange(index-__ARRAYBASE__,1 )
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Resize(newSize AS INT) AS VOID
			IF SELF:CheckLock()
				IF newSize == 0
					_internalList:Clear()
				ELSE
					LOCAL count := _internalList:Count AS INT
					IF newSize <= count
						_internalList:RemoveRange(newSize, count - newSize)
					ELSE
						count+=1
						DO WHILE count <= newSize
							LOCAL u := T{} AS T
							_internalList:Add(u)
							count++
						ENDDO
					ENDIF
				ENDIF
			ENDIF
			RETURN

			#endregion
        /// <inheritdoc />
		PUBLIC OVERRIDE METHOD ToString() AS STRING
			RETURN string.Format("[{0}]",_internalList:Count)

		INTERNAL METHOD Sort(startIndex AS INT, count AS INT, comparer AS IComparer<T>) AS VOID
            IF startIndex <= 0
                startIndex := 1
            ENDIF
            IF count < 0
                count := _internalList:Count - startIndex + __ARRAYBASE__
            ENDIF
			_internalList:Sort(startIndex-__ARRAYBASE__ ,count,comparer)
			RETURN

		INTERNAL METHOD Sort(comparer AS IComparer<T>) AS VOID
			_internalList:Sort(comparer)
			RETURN

		INTERNAL METHOD Swap(position AS INT, element AS T) AS T
			LOCAL original := _internalList[position - __ARRAYBASE__] AS T
			_internalList[ position - __ARRAYBASE__]:=element
			RETURN original

		INTERNAL METHOD Swap(position AS INT, element AS OBJECT) AS T
			//try
			VAR elementT := (T) (OBJECT) element
			RETURN Swap( position, elementT)
			//catch
			//	throw ArgumentException{"Parameter is of incorrect type "+element:GetType():FullName,nameof(element)}
			//end try

		INTERNAL METHOD Tail() AS T
			RETURN _internalList:LastOrDefault()

			#region locking
		INTERNAL METHOD Lock(lLocked AS LOGIC) AS LOGIC
			LOCAL wasLocked AS LOGIC
			wasLocked := SELF:_islocked
			SELF:_islocked := lLocked
			RETURN wasLocked
			/// Is the array locked?
		PROPERTY Locked AS LOGIC GET _islocked

		INTERNAL METHOD CheckLock AS LOGIC
			IF SELF:_islocked
				THROW Error{Gencode.EG_Protection}
			ENDIF
			RETURN ! SELF:_islocked

			#endregion

		#region operators
		/// Implicitely convert an array of USUALs to a typed array. Note that the usuals must contain a value of the correct type.
		STATIC OPERATOR IMPLICIT ( a AS ARRAY) AS __ArrayBase<T>
			VAR aResult := __ArrayBase<T>{}
			LOCAL oErr AS Error
			FOREACH VAR u IN a
				LOCAL o := u AS OBJECT
				IF o IS T
					aResult:Add( (T) o)
				ELSE
					LOCAL nArg AS INT
					LOCAL oActType AS System.Type
					oActType := o:GetType()
					nArg := a:_internalList:IndexOf(u)+1
					oErr := Error{GenCode.EG_DATATYPE}
					oErr:Arg := "Array Element : "+nArg:ToString()
					oErr:Description := "Cannot convert array element " +nArg:ToString() + " from type "+oActType:ToString()+" to type "+TYPEOF(T):ToString()
					THROW oErr
				ENDIF
			NEXT
			RETURN aResult

		/// Implicitely convert a typed array to an array of USUALs.
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS ARRAY
			VAR aResult := __Array{}
			FOREACH VAR o IN a
				aResult:Add(  o)
			NEXT
			RETURN aResult

        /// Implicitely convert a typed Array to an OBJECT[].
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS OBJECT[]
			LOCAL aResult := List<OBJECT>{} AS List<OBJECT>
			FOREACH VAR o IN a
				aResult:Add( o)
			NEXT
			RETURN aResult:ToArray()

    #endregion

	END	CLASS
END NAMESPACE

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System.Collections
USING System.Collections.Generic
USING System.Linq
USING System.Diagnostics
USING System.Reflection
USING XSharp
BEGIN NAMESPACE XSharp
	/// Internal type that implements the new TYPED ARRAY type.

	/// This type has methods and properties that normally are never directly called from user code.
	///
	PUBLIC CLASS __ArrayBase<T> IMPLEMENTS INamedIndexer, IEnumerable<T> WHERE T IS NEW()
		INTERNAL _internalList AS List<T>
		PRIVATE _islocked AS LOGIC
		#region constructors
		/// Create an empty array
		CONSTRUCTOR()
			_internalList := List<T>{}
			RETURN

		/// Create an array with a certain number of elements. Each element will be filled with a default value.
		CONSTRUCTOR(capacity AS DWORD)
			_internalList := List<T>{ (INT) capacity}
			_internalList:AddRange(Enumerable.Repeat(DEFAULT(T),(INT) capacity))
			RETURN

		/// Create an array and fill it with elements from an existing collection.
		CONSTRUCTOR( collection AS IEnumerable<T>)
			_internalList := List<T>{collection}
			RETURN

		/// Create an array and fill it with elements from an existing .Net array of objects. Note that the objects must be of the right type.
		CONSTRUCTOR( elements AS OBJECT[] )
			SELF()
			IF elements == NULL
				THROW ArgumentNullException{NAMEOF(elements)}
			ENDIF
			FOREACH element AS OBJECT IN elements
				IF element == NULL
					_internalList:add(DEFAULT(T))
				ELSEIF element IS T
					_internalList:Add( (T) element)
				ELSE
					THROW ArgumentException{"Object array contains element of incorrect type "+element:GetType():FullName}
				ENDIF
			NEXT
			RETURN

		/// Create an array and fill it with elements from an existing .Net array.
		CONSTRUCTOR( elements AS T[] )
			_internalList := List<T>{elements}
			RETURN
			#endregion

		#region properties
		/// Is the array empty.
		PUBLIC PROPERTY IsEmpty AS LOGIC GET _internalList:Count == 0
		/// Length of the array.
		PUBLIC PROPERTY Length AS DWORD GET (DWORD) _internalList:Count
        /// Length of the array as integer.
        PUBLIC PROPERTY Count AS INT GET _internalList:Count
		#endregion

		#region Enumerators
		PUBLIC METHOD IEnumerable<T>.GetEnumerator() AS IEnumerator<T>
			RETURN _internalList:GetEnumerator()

		PUBLIC METHOD IEnumerable.GetEnumerator() AS IEnumerator
			RETURN _internalList:GetEnumerator()

			#endregion

		#region Cloning

		INTERNAL METHOD Clone() AS __ArrayBase<T>
			LOCAL aResult AS __ArrayBase<T>
			LOCAL nCount AS DWORD
			nCount := (DWORD) _internalList:Count
			aResult := (__ArrayBase<T>) Activator.CreateInstance(SELF:GetType(), NULL)
			aResult:Resize( _internalList:Count )
		    // warning, nCount-1 below will become MAXDWORD for nCount == 0
			IF nCount == 0
				RETURN aResult
            ENDIF
			FOR VAR I := 0 TO nCount-1
				aResult:_internalList[i] := _internalList[i]
			NEXT
			RETURN aResult

			#endregion

		#region Indexers and TO GET / SET Elements.
	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The element stored at the specified location in the array.</returns>
        PUBLIC METHOD __GetElement(index AS INT) AS T
			RETURN SELF:_internalList[ index ]

	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name='e'>New element to store in the array at the position specified</param>
        /// <returns>The new element</returns>
		PUBLIC METHOD __SetElement(e AS T,index AS INT) AS T
			IF SELF:CheckLock()
				_internalList[index]:=e
			ENDIF
			RETURN e

		PRIVATE METHOD __GetProperty(sName AS STRING) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL oProp AS PropertyInfo
			type := TYPEOF(T)
			oProp := type:GetProperty(sName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
			IF oProp == NULL_OBJECT
				THROW ArgumentException{"Unknown property: "+sName}
			ENDIF
			RETURN oProp

		PRIVATE METHOD __GetIndexer(lNumeric AS LOGIC) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL aProps AS PropertyInfo[]
			type := TYPEOF(T)
			aProps := type:GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
            FOREACH oProp AS PropertyInfo IN aProps
                IF !oProp:Name:Tolower() == "item"
                    LOOP
                ENDIF
                LOCAL pars := oProp:GetIndexParameters() AS ParameterInfo[]
                IF pars:Length > 0
                    LOCAL par := pars[__ARRAYBASE__] AS ParameterInfo
                    SWITCH Type.GetTypeCode(par:ParameterType)
                    CASE TypeCode.Int32
                    CASE TypeCode.Int64
                    CASE TypeCode.UInt32
                    CASE TypeCode.UInt64
                        IF (lNumeric)
                            RETURN oProp
                        ENDIF
                    CASE TypeCode.String
                        IF (!lNumeric)
                            RETURN oProp
                        ENDIF
                    END SWITCH
                ENDIF

            NEXT
			RETURN NULL

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
		/// <returns>The element stored at the indicated location in the collection.</returns>
		PUBLIC PROPERTY SELF[index AS INT] AS T
			GET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				RETURN _internalList[index ]
			END GET
			SET
				IF SELF:CheckLock()
					IF index > _internalList:Count-1
						THROW ArgumentOutOfRangeException{}
					ENDIF
					_internalList[index] := VALUE
				ENDIF
			END SET
		END PROPERTY

        /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
        /// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="index2"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, index2 AS INT] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[index2]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(TRUE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{index2})
                ENDIF
                THROW ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[index2] := VALUE
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(TRUE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(VALUE, oProp:PropertyType), <OBJECT>{index2} )
                        RETURN
                    ENDIF
                    THROW ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}
				ENDIF
			END SET
		END PROPERTY

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="name"><include file="RTComments.xml" path="Comments/NameBasedIndexParam/*" /></param>
		/// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, name AS STRING] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[name]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(FALSE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{name})
                ENDIF
				oProp	 := __GetProperty( name)
				RETURN oProp:GetValue(oElement, NULL)
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW ArgumentOutOfRangeException{}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[name] := VALUE
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(FALSE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(VALUE, oProp:PropertyType), <OBJECT>{name} )
                        RETURN
                    ENDIF
					oProp	 := __GetProperty( name)
					oProp:SetValue(oElement, NULL, VALUE)
				ENDIF
			END SET
		END PROPERTY

		#endregion

		#region Insert and Delete elements
        /// <exclude />
		PUBLIC METHOD Add(u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:Add(u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Delete(position AS INT) AS __ArrayBase<T>
			SELF:RemoveAt(position)
			SELF:Add(T{})
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD Insert(index AS INT,u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveAt(_internalList:Count - 1)
				_internalList:Insert((INT) index-__ARRAYBASE__ ,u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Insert(position AS INT) AS __ArrayBase<T>
			SELF:Insert( position, DEFAULT(T))
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD RemoveAt(index AS INT) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveRange(index-__ARRAYBASE__,1 )
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Resize(newSize AS INT) AS VOID
			IF SELF:CheckLock()
				IF newSize == 0
					_internalList:Clear()
				ELSE
					LOCAL count := _internalList:Count AS INT
					IF newSize <= count
						_internalList:RemoveRange(newSize, count - newSize)
					ELSE
						count+=1
						DO WHILE count <= newSize
							LOCAL u := T{} AS T
							_internalList:Add(u)
							count++
						ENDDO
					ENDIF
				ENDIF
			ENDIF
			RETURN

			#endregion
        /// <inheritdoc />
		PUBLIC OVERRIDE METHOD ToString() AS STRING
			RETURN string.Format("[{0}]",_internalList:Count)

		INTERNAL METHOD Sort(startIndex AS INT, count AS INT, comparer AS IComparer<T>) AS VOID
            IF startIndex <= 0
                startIndex := 1
            ENDIF
            IF count < 0
                count := _internalList:Count - startIndex + __ARRAYBASE__
            ENDIF
			_internalList:Sort(startIndex-__ARRAYBASE__ ,count,comparer)
			RETURN

		INTERNAL METHOD Sort(comparer AS IComparer<T>) AS VOID
			_internalList:Sort(comparer)
			RETURN

		INTERNAL METHOD Swap(position AS INT, element AS T) AS T
			LOCAL original := _internalList[position - __ARRAYBASE__] AS T
			_internalList[ position - __ARRAYBASE__]:=element
			RETURN original

		INTERNAL METHOD Swap(position AS INT, element AS OBJECT) AS T
			//try
			VAR elementT := (T) (OBJECT) element
			RETURN Swap( position, elementT)
			//catch
			//	throw ArgumentException{"Parameter is of incorrect type "+element:GetType():FullName,nameof(element)}
			//end try

		INTERNAL METHOD Tail() AS T
			RETURN _internalList:LastOrDefault()

			#region locking
		INTERNAL METHOD Lock(lLocked AS LOGIC) AS LOGIC
			LOCAL wasLocked AS LOGIC
			wasLocked := SELF:_islocked
			SELF:_islocked := lLocked
			RETURN wasLocked
			/// Is the array locked?
		PROPERTY Locked AS LOGIC GET _islocked

		INTERNAL METHOD CheckLock AS LOGIC
			IF SELF:_islocked
				THROW Error{Gencode.EG_Protection}
			ENDIF
			RETURN ! SELF:_islocked

			#endregion

		#region operators
		/// Implicitely convert an array of USUALs to a typed array. Note that the usuals must contain a value of the correct type.
		STATIC OPERATOR IMPLICIT ( a AS ARRAY) AS __ArrayBase<T>
			VAR aResult := __ArrayBase<T>{}
			LOCAL oErr AS Error
			FOREACH VAR u IN a
				LOCAL o := u AS OBJECT
				IF o IS T
					aResult:Add( (T) o)
				ELSE
					LOCAL nArg AS INT
					LOCAL oActType AS System.Type
					oActType := o:GetType()
					nArg := a:_internalList:IndexOf(u)+1
					oErr := Error{GenCode.EG_DATATYPE}
					oErr:Arg := "Array Element : "+nArg:ToString()
					oErr:Description := "Cannot convert array element " +nArg:ToString() + " from type "+oActType:ToString()+" to type "+TYPEOF(T):ToString()
					THROW oErr
				ENDIF
			NEXT
			RETURN aResult

		/// Implicitely convert a typed array to an array of USUALs.
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS ARRAY
			VAR aResult := __Array{}
			FOREACH VAR o IN a
				aResult:Add(  o)
			NEXT
			RETURN aResult

        /// Implicitely convert a typed Array to an OBJECT[].
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS OBJECT[]
			LOCAL aResult := List<OBJECT>{} AS List<OBJECT>
			FOREACH VAR o IN a
				aResult:Add( o)
			NEXT
			RETURN aResult:ToArray()

    #endregion

	END	CLASS
END NAMESPACE