如何设置和检查无值作为枚举?

时间:2016-02-24 23:21:28

标签: delphi enums delphi-xe7

我将一些常用值转换为枚举值。但是我对那些缺失值/无值也有意义的问题有所了解:

vDataType:string;

If vDataType = '' Then // no datatype assigned, yet -> handle appropriately
else if vDataType = 'PROJECT' then // process as project record
else if vDataTpye = 'GROUP' then // process as project group record
else if vDataType = 'TASK' then // process as project task

如果我现在设置:

TDataType = (dtProject, dtGroup, dtTask);

var vDatatype:TDataType;

我可以用

If vDataType = dtProject Then ...
else if vDataType = dtGroup then ...
else if vDataType = dtTaks then ...

但由于第一个元素是dtProject为0,我现在如何检查没有值,替换为:if vDatatype = '' then...

记录都在同一个数组中,因此无值具有意义,因为它将记录与标记为项目,组或任务的其他记录区分开来。记录在导入记录的过程中被标记,我想避免将其中一个枚举值(如dtNone)设置为不是dtProject,dtGroup或dtTask的所有记录。

修改

这是我被卡住的例子:

TData = record
    LineID:integer;
    FullLine:string;
    //...
    DataType:string;
end;

var vArray:TArray<TData>;

procedure ProcessDataAfterImport;
var i:integer;
begin
  for i:=0 to High(vArray) do
  begin
    if Copy(vArray[i].FullLine,1,4)='PRJ=' then
        vArray[i].DataType := 'PROJECT'
    else if Copy(vArray[i].FullLine,1,4)='GRP=' then
        vArray[i].DataType := 'GROUP'
    else if Copy(vArray[i].FullLine,1,4)='TSK=' then
        vArray[i].DataType := 'TASK';
  end;
end;

procedure ProcessProjects;
var i:integer;    
begin
  for i:=0 to High(vArray) do
  if vArray[i].DataType = 'PROJECT' Then
     ParseProjectRecord(vArray[i]);
end;

我有许多与ProcessProjects类似的方法来处理基于DataType的记录,我不想使用&#39; PROJECT&#39;除了枚举之外的所有地方都是整数,我认为它也更快,不容易出现像“PROJCET”这样的错误。我数了一下'PROJECT&#39;使用了55次。 &#39; GROUP&#39;和&#39;任务&#39;少了一些,但后来我有其他的例子使用类似的字符串值来指定记录类型。

3 个答案:

答案 0 :(得分:3)

您似乎要求的是不可能的。

很难说没有看到你的案例中涉及的更多代码但是我怀疑使用空字符串 - 无论是偶然还是设计 - 都在利用字符串是Delphi中为数不多的类型之一的事实在声明为局部变量时由运行时初始化。这还包括 - 例如 - 接口引用和动态数组。

这些类型对局部变量的这种特殊处理是必要的,因为运行时以特殊方式处理这些类型,这些方式依赖于这些类型的变量处于有效初始状态的确定性。

e.g。 String 的RTTI中的长度字段必须正确反映分配用于保存该字符串中的字符的内存,否则将在修改该字符串时导致内存错误。界面必须为NIL,以避免在最初分配其他值时对发布进行无效调用。等等

声明为类成员变量的其他类型的值,例如,可能出现以在类的新实例中初始化,但这是零的结果 - 这些类的新分配实例的内存,而不是任何实际的初始化。

String更改为枚举时的问题是,枚举不需要(因此也不会接收)任何此类特殊处理,因此必须 明确初始化。

注意:即使枚举是自动初始化的,它们也会初始化为0(零),即枚举的第一个成员(除非第一个成员已明确指定了非零序数值。)

考虑到这一点,这意味着如果要求枚举变量能够指示No ValueNot Set,则此必须作为有效值出现在枚举本身,您必须根据需要显式初始化该类型的变量。

注意:如果您确保此Not set值是枚举的第一个成员,那么正如您所观察到的那样,它将具有值0(零)这意味着此类型的任何类成员变量将在该类的新实例中使用此Not set值自动“初始化”。

但对于本地变量,记录成员等,您必须明确初始化它,就像您必须初始化Integer或{ {1}}等等。

答案 1 :(得分:3)

在Delphi中,您可以设置枚举的值。例如,你可以写:

TDataType = (dtNone=-1, dtProject, ...);

可能会解决您将0分配给dtNone的问题。

然而,正如其他人所说,如果没有更多代码,很难看出这会带来什么。目前,枚举是否会产生任何差异而不是字符串并不明显。

答案 2 :(得分:3)

你可以使用潜在的危险方法

If vDataType = dtProject Then ...
else if vDataType = dtGroup then ...
else if vDataType = dtTaks then ...
else // no predefined datatype assigned, yet -> handle appropriately

如果没有满足先前的if和else if条件,那么将执行最后的else。

现在为什么这有潜在危险?

正如Deltics已经在他的回答局部变量中解释的那样,记录成员等没有被初始化为某个默认状态,但是只为它们分配了一定的内存位置,那么存储在那里的内存数据是可能的。之前被分配到某个位置的位置可能包含将转换为您的set值之一的数据,即使您尚未分配它。

所以我仍然建议您定义默认设置值,并在每次都不分配任何其他设置时分配它。