如何为TEncoding类型的函数参数设置默认值?

Jan*_*gen 6 delphi unicode encoding delphi-xe2

从D2007转换为XE2,我转换了这个功能

function Add_Line( FileStream : TFileStream; ALine : string) : boolean;
Run Code Online (Sandbox Code Playgroud)

function Add_Line( FileStream : TFileStream; ALine : string; Enc: TEncoding = nil) : boolean;
var
  AStr: ANSISTring;
begin
  Result := True;
  if Enc = nil then Enc := TEncoding.ANSI;
  try
//Old    FileStream.WriteBuffer( Pointer(ALine)^, Length(ALine) );
    if Enc = TEncoding.UTF8 then
      AStr := UTF8Encode(ALine)
    else
      AStr := ANSIString(ALine);
    FileStream.WriteBuffer( AStr[1], Length(ALine) );
    end;
  except
    Result := False;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

理由:

  • 尽可能少地使用Add_Line更改代码

  • 接受自动更改为Unicode,仅在最后时刻写入8位文本文件(这在XML和CSV中使用).如果我们想要的话,未来我们仍然可以转向UTF-16文件.

我本来希望定义类似的东西:

function Add_Line( FileStream : TFileStream; ALine : string; Enc: TEncoding = TEncoding.ANSI) : boolean;
Run Code Online (Sandbox Code Playgroud)

但编译器抱怨;-)

有可能吗?

小智 12

默认参数必须是编译时常量,但如果您需要更高级的东西,则可以创建重载:

function Add_Line( FileStream : TFileStream; ALine : string) : boolean; overload;
function Add_Line( FileStream : TFileStream; ALine : string; Enc: TEncoding) : boolean; overload;


function Add_Line( FileStream : TFileStream; ALine : string) : boolean;
begin
  Result := Add_Line(FileStream, ALine, TEncoding.ANSI);
end;
Run Code Online (Sandbox Code Playgroud)

您甚至可以添加inline关键字以获得与默认参数产生的完全相同的生成代码,如果它有效.

注意:除了TEncoding.ANSI和之外,您似乎不支持任何其他内容TEncoding.UTF8.在这种情况下,TEncoding参数似乎有点过分,您可以使用UTF8: Boolean参数(或者重新编写代码以使用任意编码CodePage).

注2:FileStream.WriteBuffer( AStr[1], Length(ALine) );错误是因为Length(ALine)并且Length(AStr)不必相同,你应该使用Length(AStr).另外,AStr[1]AStr一个空字符串时可能导致异常,你可以添加一个特殊情况,只WriteBufferAStr非空时调用.


Rem*_*eau 6

其他人评论了如何为TEncoding参数指定默认值.我想指出你的使用TEncoding一般是完全错误的.

TEncoding.UTF8不是获取UTF-8编码对象的唯一方法(TEncoding.GetEncoding(65001)另一种方式),因此TEncoding.UTF8具体检查是不对的.更糟糕的是,你完全忽略了任何非UTF8编码,只是将其他任何东西编码到平原上AnsiString,这完全违背了使用的全部目的TEncoding.例如,用户可以传入ISO-8859-X编码对象,并且您的输出不会像用户请求的那样进行ISO编码.您也可以将参数更改为UseUTF8: Boolean = False参数,因为这是您有效使用它的方式:

function Add_Line( FileStream : TFileStream; ALine : string; UseUTF8: Boolean = False) : boolean;  
var  
  AStr: AnsiString;  
begin  
  Result := True;  
  try  
    if UseUTF8 then  
      AStr := UTF8Encode(ALine)  
    else  
      AStr := AnsiString(ALine);  
    if AStr <> '' then
      FileStream.WriteBuffer( AStr[1], Length(AStr) );  
  except  
    Result := False;  
  end;  
end;  
Run Code Online (Sandbox Code Playgroud)

正确的使用方法TEncoding是让它进行实际编码,不要自己编码:

function Add_Line( FileStream : TFileStream; ALine : string; Enc: TEncoding = nil) : boolean; 
var 
  AStr: TBytes; 
begin 
  if ALine = '' then
  begin
    Result := True;
    Exit;
  end; 
  Result := False;
  try 
    if Enc = nil then Enc := TEncoding.Ansi; 
    AStr := Enc.GetBytes(ALine); 
    // GetBytes() returns 0 bytes if it fails to encode, it does not raise an exception!
    if Length(AStr) = 0 then Exit;
    FileStream.WriteBuffer( AStr[0], Length(AStr) )
  except 
    Exit;
  end; 
  Result := True;
end; 
Run Code Online (Sandbox Code Playgroud)