1

I'm doing a project with delphi. The project has c # codes. I'm using the byte array in the project. But I get an error. C # codes:

public class DataTransmitEventArgs : EventArgs
    {
        public DataTransmitEventArgs(byte[] transmittedBytes)
        {
            fTransmittedBytes = transmittedBytes;
        }
        byte[] fTransmittedBytes;
        public byte[] TransmittedBytes
        {
            get { return fTransmittedBytes; }
        }
    }

and my Delphi codes:

DataTransmitEventArgs = class

 public
 fTransmittedBytes: array of byte;
 constructor  Create(transmittedBytes: array of byte);overload;
 property TransmittedBytes[index: byte]:Byte read fTransmittedBytes;
 end;

  constructor DataTransmitEventArgs.Create(transmittedBytes: array of byte);
     begin
             fTransmittedBytes := transmittedBytes;
     end;

how do i do these c # codes with delphi

1

1 Answer 1

3

You forgot to specify what error message you receive and on what line (always do that!), but almost certainly it was E2008: Incompatible types at the property line.

According to the documentation, which should always be your first source for information, an array property cannot have fields (like fTransmittedBytes) as its access specifiers (read or write). Instead, they must be methods:

For array properties, access specifiers must list methods rather than fields. The method in a read specifier must be a function that takes the number and type of parameters listed in the property's index parameter list, in the same order, and whose result type is identical to the property's type. The method in a write specifier must be a procedure that takes the number and type of parameters listed in the property's index parameter list, in the same order, plus an additional value or const parameter of the same type as the property.

Let's do an example:

type
  TTest = class
  private
    FData: array of Byte;
  public
    property Data[Index: Integer]: Byte read FData write FData;
  end;

violates this requirement and emits E2008 at the read (and write if you fix the read).

Instead, you must do

type
  TTest = class
  private
    FData: array of Byte;
    function GetData(Index: Integer): Byte;
    procedure SetData(Index: Integer; const Value: Byte);
  public
    property Data[Index: Integer]: Byte read GetData write SetData;
  end;

{ TTest }

function TTest.GetData(Index: Integer): Byte;
begin
  Result := FData[Index];
end;

procedure TTest.SetData(Index: Integer; const Value: Byte);
begin
  FData[Index] := Value;
end;

If you want additional safety, do (uses Math)

function TTest.GetData(Index: Integer): Byte;
begin
  if InRange(Index, Low(FData), High(FData)) then
    Result := FData[Index]
  else
    raise Exception.CreateFmt('Index out of bounds: %d', [Index]);
end;

procedure TTest.SetData(Index: Integer; const Value: Byte);
begin
  if InRange(Index, Low(FData), High(FData)) then
    FData[Index] := Value
  else
    raise Exception.CreateFmt('Index out of bounds: %d', [Index]);
end;

Alternatively, it is quite possible to skip the property and have the field be public:

type
  TTest = class
  public
    Data: array of Byte;
  end;

Finally, it is possible to have the field private but a public property of a dynamic array type:

type
  TTest = class
  private
    FData: TArray<Byte>;
  public
    property Data: TArray<Byte> read FData write FData;
  end;

If you are on a pre-generics version of Delphi, TArray<Byte> is obviously not available, so you then have to define your own type: type ByteArray = array of Byte.


In addition, you have

constructor  Create(transmittedBytes: array of byte);overload;

which should be

constructor Create(const ATransmittedBytes: array of Byte); overload;

Always use const on open array parameters:

When you pass an array as an open array value parameter, the compiler creates a local copy of the array within the routine's stack frame. Be careful not to overflow the stack by passing large arrays.


Finally, your

fTransmittedBytes := transmittedBytes;

will not compile, either, because you cannot simply assign an open array to a dynamic array.

Instead, you can change the parameter to a dynamic array type:

constructor Create(const ATransmittedBytes: TArray<Byte>); overload;

You might then also want to Copy the array:

FTransmittedBytes := Copy(ATransmittedBytes);

Alternatively, you can use SetLength and a simple for loop to copy the array:

SetLength(FTransmittedBytes, Length(ATransmittedBytes));
for i := 0 to High(ATransmittedBytes) do
  FTransmittedBytes[i] := ATransmittedBytes[i];

The lower bound of an open array is always 0.

Sign up to request clarification or add additional context in comments.

1 Comment

Even though the lower bound of open arrays is always 0, I'd still recommend using Low(ATransmittedBytes) - just to get in the habit of using Low/High on array index limits.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.