是否可以将对象函数作为参数传递给过程而不是传递整个对象?
我有一个记录定义,其函数定义为公共类参数,例如:
TMyRecord = record
public
class function New(const a, b: Integer): TMyRecord; static;
function GiveMeAValue(inputValue: integer): Single;
public
a, b: Integer;
end;
Run Code Online (Sandbox Code Playgroud)
该功能可能是这样的:
function TMyRecord.GiveMeAValue(inputValue: Integer): Single;
begin
RESULT := inputValue/(self.a + self.b);
end;
Run Code Online (Sandbox Code Playgroud)
然后我希望定义一个调用类函数的过程,GiveMeAValue
但我不想将它传递给整个记录.我可以做这样的事情,例如:
Procedure DoSomething(var1: Single; var2, var3: Integer, ?TMyRecord.GiveMeAValue?);
begin
var1 = ?TMyRecord.GiveMeAValue?(var2 + var3);
//Do Some Other Stuff
end;
Run Code Online (Sandbox Code Playgroud)
如果是,那么我如何正确地将该函数作为过程参数传递?
我有一个非常简单的3D矢量类定义TVector3D
,以及一些用于实现该TVector3D.Normalise
功能的方法.如果我将Normalise
函数传递给已经规范化的向量,我希望它返回我传递给它的向量.在这里我已经习惯了,Result := Self
但我有一些疯狂的回报.
控制台应用程序:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TVector3D = Class
public
x : Single;
y : Single;
z : Single;
constructor Create(x : Single;
y : Single;
z : Single);
function GetMagnitude() : Single;
function IsUnitVector() : Boolean;
function Normalise() : TVector3D;
end;
constructor TVector3D.Create(x : Single;
y : Single;
z : Single);
begin
Self.x := x;
Self.y := y;
Self.z := z;
end;
function TVector3D.GetMagnitude; …
Run Code Online (Sandbox Code Playgroud) 我正在运行Delphi RAD Studio XE2.我最近一直在玩文件流,并发现一些有趣的结果引导我这个问题.
TStreamReader
Delphi中最佳缓冲区大小是多少?例如,我在表单中加载了一个200万行的1GB文件doubleTABdoubleTABdouble
.如果我TStringList
使用以下代码将其加载到a中,我会针对不同的缓冲区大小获得显着不同的结果.结果我的意思是处理速度和RAM使用率.
reader := TStreamReader.Create(fileLocation, TEncoding.UTF8, True, NumBytes);
try
stringList.BeginUpdate;
try
stringList.Clear;
while not reader.EndOfStream do
stringList.Add(reader.ReadLine);
finally
stringList.EndUpdate;
end;
finally
reader.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
最佳缓冲区大小似乎介于1024和4096之间.如果设置小于1024,它似乎线性减速并且似乎使用更多RAM.如果它设置在4096以上,它似乎会以指数方式减速.
为什么我会看到这些行为,如何确定任务的最佳缓冲区大小?另外,最大缓冲区大小是多少?
编辑
我运行以下代码以使用上述文件大小提取运行时间:
startTime := Now();
myStreamReader := TStreamReader.Create(fileLocation, TEncoding.UTF8, True, numBytes);
myStringList := TStringList.Create;
try
myStringList.BeginUpdate;
try
myStringList.Clear;
while not myStreamReader.EndOfStream do
myStringList.Add(myStreamReader.ReadLine);
finally
myStringList.EndUpdate;
end;
finally
myStreamReader.Free;
end;
processTime := Now() - startTime;
myStringList.Free;
Run Code Online (Sandbox Code Playgroud)
示例运行时间被提取为:
Buffer Size 32. Done in 69s
Buffer Size 64. Done …
Run Code Online (Sandbox Code Playgroud) 假设我在一个单元中有一个简单的记录,例如:
TVector2D = record
public
class function New(const x, y: Accuracy): TVector2D; static;
public
x, y: Accuracy;
end;
Run Code Online (Sandbox Code Playgroud)
然后我在使用上述记录集构建的同一单元中有第二条记录,例如:
TMatrix3D = record
public
class function New(const row1, row2, row3: TVector3D): TMatrix3D; static;
public
Index : array [0..2] of TVector3D;
end;
Run Code Online (Sandbox Code Playgroud)
然后我定义轴方向常数如下:
//Unit vector constants
const
iHat : TVector3D = (x: 1; y: 0; z: 0);
jHat : TVector3D = (x: 0; y: 1; z: 0);
kHat : TVector3D = (x: 0; y: 0; z: 1);
Run Code Online (Sandbox Code Playgroud)
我现在想要使用上面的常量来定义另一个常量,例如:
identity : TMatrix3D = …
Run Code Online (Sandbox Code Playgroud) 记下以下记录:
TVector2D = record
public
class operator Equal(const V1, V2: TVector2D): Boolean;
class operator Multiply(const D: Accuracy; const V: TVector2D): TVector2D;
class operator Divide(const V: TVector2D; const D: Accuracy): TVector2D;
class function New(const x, y: Accuracy): TVector2D; static;
function Magnitude: Accuracy;
function Normalised: TVector2D;
public
x, y: Accuracy;
end;
Run Code Online (Sandbox Code Playgroud)
使用定义为的方法:
class operator TVector2D.Equal(const V1, V2: TVector2D): Boolean;
var
A, B: Boolean;
begin
Result := (V1.x = V2.x) and (V1.y = V2.y);
end;
class operator TVector2D.Multiply(const D: Accuracy; const V: TVector2D): …
Run Code Online (Sandbox Code Playgroud) 下面是一个简单的控制台应用程序,然后生成10组3个随机数,并将它们打印到控制台窗口和文本文件"Output.txt".
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
var
outputFile: TextFile;
i: Integer;
a,b,c: Single;
begin
try
Randomize;
AssignFile(outputFile, 'Output.txt');
ReWrite(outputFile);
for i := 0 to 9 do
begin
a := Random;
b := Random;
c := Random;
WriteLn(FloatToStr(a) + Char(9) + FloatToStr(b) + Char(9) + FloatToStr(c));
WriteLn(outputFile, FloatToStr(a) + Char(9) + FloatToStr(b) + Char(9) + FloatToStr(c));
end;
Close(outputFile);
Sleep(10000);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
仅当我包含第26行时,文本文件才包含与控制台窗口相同的信息:
关闭(OUTPUTFILE);
如果我从代码中省略了这一点,我希望无论如何都能将相同的数据打印到文本文件中,但实际打印在文本文件中的内容与前9行相同,然后是不完整的最终行.
为什么会这样?由于省略了Close程序,最后一行只能通过什么过程写入?
我正在运行Delphi RAD Studio XE2.
我有一些非常大的文件,每个文件都包含大量的行.线条本身很小 - 只有3个标签分隔的双打.我想将文件加载到TStringList
使用中,TStringList.LoadFromFile
但这会引发大文件的异常.
对于200万行(约1GB)的文件,我得到了EIntOverflow
例外.对于较大的文件(例如,2000万行和大约10GB),我得到了ERangeCheck
例外.
我有32GB的RAM可供使用,我只是想加载这个文件并快速使用它.这里发生了什么,我有什么其他选择?我可以使用带有大缓冲区的文件流将此文件加载到TStringList中吗?如果是这样,请举一个例子.
我正在运行RAD Studio Delphi XE2.我的一个.pas文件似乎有些奇怪.我的unit1.pas中的许多线路都被简单的'º'取代而其他线路丢失了.我留下了原始文件中间某处的一小段代码.我可以通过某种方式反编译unit1.dcu来获取原来的unit1.pas吗?
另外,为什么会发生这种情况?你以前听说过这个吗?代码运行但很明显,我无法编辑任何我看不到的内容.
delphi ×8
delphi-xe2 ×4
filestream ×2
record ×2
buffer ×1
code-layout ×1
constants ×1
decompiling ×1
delphi-xe3 ×1
function ×1
procedure ×1
readfile ×1
syntax-error ×1
text-files ×1
tstringlist ×1