Search code examples
delphidelphi-xe2indydelphi-xe6

No Overload Version of Write


I am shareing a project with someone codeing in xe6, I am using xe2 version 16. I get this error

There is no overloaded version of 'write' that can be called with these arguments

at this code.

  {$IF CompilerVersion >= 19}
  // Modified code for Delphi XE5 & later
  tcpConnection.IOHandler.Write(TheMsg, IndyTextEncoding.Default  );
  {$ELSE}
  // Original XE2 code
  tcpConnection.IOHandler.Write(TheMsg, TIdTextEncoding.Default);
  {$IFEND}

I have also added idGlobal in the uses. Any other reason this would give error?


Solution

  • IndyTextEncoding() is a series of overloaded functions, all taking an input parameter, all returning an IIdTextEncoding interface:

    function IndyTextEncoding(AType: IdTextEncodingType): IIdTextEncoding; overload;
    function IndyTextEncoding(ACodepage: Word): IIdTextEncoding; overload;
    function IndyTextEncoding(const ACharset: String): IIdTextEncoding; overload;
    {$IFDEF DOTNET}
    function IndyTextEncoding(AEncoding: System.Text.Encoding): IIdTextEncoding; overload;
    {$ENDIF}
    {$IFDEF HAS_TEncoding}
    function IndyTextEncoding(AEncoding: TEncoding): IIdTextEncoding; overload;
    {$ENDIF}
    

    IIdTextEncoding does not have a Default property (or any other encoding type properties). IIdTextEncoding was introduced to break away from Embarcadero's TEncoding class and simplify Indy's memory management of codepage/charset handlers.

    In earlier versions of Indy, the TIdTextEncoding.Default property represented the OS default encoding. The correct way to get the OS default encoding in the latest version of Indy is to use the IndyTextEncoding_OSDefault() function:

    function IndyTextEncoding_OSDefault: IIdTextEncoding;
    

    Or the IndyTextEncoding(IdTextEncodingType) function with encOSDefault as the input parameter.

    {$IF CompilerVersion >= 19}
    // Modified code for Delphi XE5 & later
    tcpConnection.IOHandler.Write(TheMsg, IndyTextEncoding_OSDefault);
    // or: tcpConnection.IOHandler.Write(TheMsg, IndyTextEncoding(encOSDefault));
    {$ELSE}
    // Original XE2 code
    tcpConnection.IOHandler.Write(TheMsg, TIdTextEncoding.Default);
    {$IFEND}
    

    The IndyTextEncoding_Default() function, by comparison, returns an IIdTextEncoding that represents Indy's default encoding that is specified in the IdGlobal.GIdDefaultTextEncoding variable (7bit ASCII by default).

    If you want to use something that works in both Indy versions without using an {$IFDEF}, use the deprecated IndyOSDefaultEncoding() function:

    function IndyOSDefaultEncoding{$IFNDEF DOTNET}(const AOwnedByIndy: Boolean = True){$ENDIF}: IIdTextEncoding;
    

    tcpConnection.IOHandler.Write(TheMsg, IndyOSDefaultEncoding);
    

    That being said, note that the OS default encoding varies from one machine to another, and from one platform to another. You should not be using it as the byte encoding in communication protocols. Use a standardized encoding instead, such as UTF-8.

    Lastly, if you are going to use {$IFDEF} or {$IF}, Indy has its own {$DEFINE} statements in IdCompilerDefines.inc, and global version constants in IdGlobal.pas, that you can use to detect Indy versions. You might consider using those instead of the CompilerVersion constant. If you were to ever upgrade Indy in XE2, for example, then your code would break. You should be checking for Indy versions, not Compiler/RTL versions, eg:

    // Indy version constants were added in 10.5.9.4850
    // TIdTextEncoding was replaced with IIdTextEncoding in 10.6.0.0
    {$IF (gsIdVersionMajor > 10) OR ((gsIdVersionMajor = 10) AND (gsIdVersionMinor >= 6))} 
    tcpConnection.IOHandler.Write(TheMsg, IndyTextEncoding_OSDefault);
    {$ELSE}
    tcpConnection.IOHandler.Write(TheMsg, TIdTextEncoding.Default);
    {$IFEND}