Friday, October 03, 2008

Delphi 2009: Unicode

W1050 WideChar reduced to byte char in set expressions.  Consider using 'CharInSet' function in 'SysUtils' unit

This compiler warning is commonly encounter in Delphi 2009.  We should change all coding using characters set with CharInSet.

For example:

Delphi 2007: A in ['a', 'b']

Delphi 2009: CharInSet(A, ['a', 'b'])

However, doing such changes will make the code not compatible with Delphi 2007.  We may construct a CharInSet function for Delphi 2007:

unit D2009_to_D2007;

interface

{$if CompilerVersion <= 18.5}
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean; inline;
{$ifend}

implementation

{$if CompilerVersion <= 18.5}
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
  Result := C in CharSet;
end;
{$ifend}

end.

The $if directive will restrict the code available for Delphi 2007 or older only.

W1057 Implicit string cast from 'ShortString' to 'string'

The following code will raise a famous W1057 compiler warning in Delphi 2009:

var s: ShortString;
    t: string;
begin
  t := s;
end;

To eliminate the warning, just cast the ShortString variable as String and it is compatible with both Delphi 2007 and 2009:

var s: ShortString;
    t: string;
begin
  t := string(s);
end;

W1057 Implicit string cast from 'AnsiString' to 'string'

The following code will raise a famous W1057 compiler warning in Delphi 2009:

var s: AnsiString;
    t: string;
begin
  t := s;
end;

To eliminate the warning, just cast the AnsiString variable as String and it is compatible with both Delphi 2007 and 2009:

var s: AnsiString;
    t: string;
begin
  t := string(s);
end;

W1058 Implicit string cast with potential data loss from 'string' to 'AnsiString'

We must take extra care for this warning.  Although using the famous cast method may solve the problem, we should only use it only if we understand what we are doing.

For example:

var s: AnsiString;
    t: string;
begin
  s := t;
end;

If we are very sure that t will contain only ansi string value, then we can perform the cast as follow safely:

var s: AnsiString;
    t: string;
begin
  s := AnsiString(t);
end;

This warning is usually happens in code invoke legacy external library (*.DLL) that supports PAnsiChar data type only.

4 comments:

Unknown said...

Is there any performance hit when doing the explicit cast? i.e. string(RawByteString)

Chau Chee Yang said...

I think performance overhead can be neglected with today's CPU.

Unknown said...

I'm interested to know, whether the compiler sets up an explicit cast in the background, or some other mechanism?

Unknown said...

Quote:
"W1057 Implicit string cast from 'AnsiString' to 'string'

The following code will raise a famous W1057 compiler warning in Delphi 2009:

var s: AnsiString;
t: string;
begin
t := s;
end;

To eliminate the warning, just cast the AnsiString variable as String and it is compatible with both Delphi 2007 and 2009:"

This can potentially be dangerous, now that Delphi uses Unicode by default. (Delphi XE as an example)

The reason is that Unicode and Ansi doesn't have the same mapping from internal representation to character.

For applications using RS232 comport like Async Pro, it is important to use AnsiString when sending any strings to the RS232.

If you just cast the AnsiString to string to get rid of the warning, your code interfacing with async pro will no longer work.