>键入别名:type NewName = OldType
> type creation:type NewType = type OldType
前者只是创建方便的速记,像C中的typedef.别名是相互兼容的,并且与其原始类型兼容.创建的类型是有意的不兼容的,不能通过定义类型转换而不显式和不安全地混合.
var nn: NewName; nt: NewType; ot: OldType; ... nn := ot; // should work nt := ot; // should break with type safety violation error. nt := NewType(ot); // Disabling type safety. Should work even if // it has no sense semantically and types really ARE incompatible.
根据我的理解,这些是帕斯卡基础知识.
现在我们来看一下某个类型和两个别名:
> System.Types.TStringDynArray =字符串数组;
> System.TArray< T> = T的数组;
>特别地,这意味着TArray< string> =字符串数组;按照定义.
现在我们来回函数返回前一个类型的别名,并将其结果提供给期待后一种别名的函数:
uses Classes,IoUtils; TStringList.Create.AddStrings( TDirectory.GetFiles('c:\','*.dll') ); TStringList.Create.AddStrings( TArray<string>( // this is required by compiler - but why ??? TDirectory.GetFiles('c:\','*.dll') ) );
由于类型违规,第一个代码段将无法编译.
第二个人高兴地编译和工作,但对未来的类型变化是脆弱的,是多余的.
QC指出编译器是正确的,RTL设计是错误的.
http://qc.embarcadero.com/wc/qcmain.aspx?d=106246
为什么编译器在这里?
为什么这些别名是不兼容的?
即使RTL设计的方式也表明它们被认为是兼容的!
PS.大卫提出了更简单的例子,没有使用TArray< T>
type T1 = array of string; T2 = array of string; procedure TForm1.FormCreate(Sender: TObject); function Generator: T1; begin Result := T1.Create('xxx','yyy','zzz'); end; procedure Consumer (const data: T2); begin with TStringList.Create do try AddStrings(data); Self.Caption := CommaText; finally Free; end; end; begin Consumer(Generator); end;
没有解释…
PPS.现在有很多doc参考.我想强调一点:虽然这个限制可能间接地继承自1949年的帕斯卡报告,但今天是2012年,德尔福与半个世纪前的实验室有很大的不同.
我命名几个BAD效果来保持这种限制,但没有看到任何好的.
讽刺的是,这种限制可以在不违反Pascal规则的情况下得到解决:在Pascal中,没有开放阵列和动态数组这样的非严格的野兽.所以让这些原始的固定数组按照自己的意愿进行限制,但是开放数组和动态数组并不是Pascal的公民,也没有必要被它的码本所限制!
请告诉Emba在QC或甚至在这里,但如果你只是通过没有表达你的意见 – 没有什么会改变!
解决方法
简化示例也是有帮助的.在例子中列入仿制药主要是使事情复杂化和混淆.
program TypeCompatibilityAndIdentity; {$APPTYPE CONSOLE} type TInteger1 = Integer; TInteger2 = Integer; TArray1 = array of Integer; TArray2 = array of Integer; TArray3 = TArray1; var Integer1: TInteger1; Integer2: TInteger2; Array1: TArray1; Array2: TArray2; Array3: TArray3; begin Integer1 := Integer2; // no error here Array1 := Array2; // E2010 Incompatible types: 'TArray1' and 'TArray2' Array1 := Array3; // no error here end.
从文档:
When one type identifier is declared using another type identifier,without qualification,they denote the same type.
这意味着TInteger1和TInteger2是相同的类型,并且确实与Integer类型相同.
在文档中有一点是这样的:
Language constructions that function as type names denote a different type each time they occur.
TArray1和TArray2的声明属于这一类别.这意味着这两个标识符表示不同的类型.
现在我们来看一下讨论兼容性的部分.这给出了一组遵循的规则来确定两种类型是兼容还是兼容兼容.我们实际上可以通过参考另一个帮助主题:Structured Types,Array Types and Assignments其中明确指出的讨论:
Arrays are assignment-compatible only if they are of the same type.
这使得清楚为什么分配Array1:= Array2导致编译器错误.
你的代码查看传递的参数,但我的重点是分配.问题是一样的,因为Calling Procedures and Functions的帮助主题解释:
When calling a routine,remember that:
- expressions used to pass typed const and value parameters must be assignment-compatible with the corresponding formal parameters.
- …….