2011-12-16 18 views
2

デルファイ。種類の相違

なぜ

type 
    myInt = Integer; 
    myNewInt = -2147483648..2147483647; 

var 
    a: myint; 
    b: myNewInt; 

begin 
    a := b; 
end; 

それは正式に、異なるタイプかかわらず正常にコンパイルされている - 一つは、ここでは他のモジュールから別の着手を宣言しています。そして

uses 
    windows; 

type 
    _FILETIMEA = record // Copy from windows.pas 
    dwLowDateTime: DWORD; 
    dwHighDateTime: DWORD; 
    end; 

var 
    x: _FILETIMEA; 
    y: windows._FILETIME; 

begin 
    x := y; 
end; 

場合type _FILETIMEA = Windows._FILETIMEかかわらず、(ラインx:=y;[DCC Error] ... E2010 Incompatible types: 'windows._FILETIME' and '_FILETIMEA'で)コンパイルエラーを引き起こすのでしょうか?

答えて

9

デルファイはダックタイピングをサポートしていません。あなたは2つの異なるレコードを持っています。それらはちょうど同じように見えますが、コンパイラには2種類あります。 2つの変数を割り当てる場合は、同じサイズのため可能なものを型キャストしなければなりません。

x := _FILETIMEA(y); 
+0

非常に悲しいです。ありがとう。 –

+6

「とても悲しい」というわけではありません。それはとても良いことです。これにより、コード内のバグや間違いを避けることができます。 –

+1

あなたは 'x:= y'で説明しましたが無効ですが、なぜ' a:= b' *が*有効であるのか説明していません。 –

7

同じことをやっていないからです。 :)デルファイは強く型付けされています(例外はほとんどありません - ほぼすべてが特定の型を持っています)。

type 
    myInt = Integer; 
    myNewInt = -2147483648..2147483647; 

これらのタイプに互換性はありません。それらは両方とも同じ型(整数)であり、同じ範囲の値をサポートします。一方を他方に割り当てることに関しては矛盾していません。

// Your unit name 
unit GuTypes; 

Type 
_FILETIMEA = record // Copy from windows.pas 
    dwLowDateTime: DWORD; 
    dwHighDateTime: DWORD; 
end; 

これはあなたのコードで定義された新しいタイプの、(それはWindows.pasのものと同じだとしても、それは同じではありません)です。 GuTypes._FileTimeAです。Windows._FileTimeAとは異なります。

これは、異なるユニットが同じタイプ名を矛盾なく使用できるため、実際には良いことです。ユニット名の前に「名前空間」を付けると、どちらを使用するのかを明確にすることができます。たとえば、あなたはあなたがGuTypesで定義した場合、およびWindowsは、第三のユニットMyAppCodeに、あなたは安全にこれを行うことができますが、宣言1を、持っている:

var 
    GFileTime: GuTypes._FILETIMEA; 
    WFileTime: Windows._FILETIMEA; 

でも種類の変更の1つが、あなたのコードはより安全です2つのタイプが誤って交換されることはないため、副作用があります。

強制的に割り当てを行うことはできますが、それは通常は悪い考えです。それは強く型付けされた言語を使うという全目的に反します。 Typecastingはコンパイラーに "私はあなたよりスマートですが、これが間違っていることを知っていますが、それを無視してやりなさい"とコンパイラーに伝えています。

よりよい解決策は、あなたがあなたの例ではyWindows._FILETYPEA)を行ったように、あなたの変数を宣言するために、または互換性のあるタイプ(type TMyFileTimeA = Windows._FILTETIMEA;)を宣言するかのいずれかだろう。

XE2 Wiki PagesType Compatibility and Identity)を参照してください。具体的にはAssignment Compatibilityセクションを見てください。

+0

'a:= b'が有効なのは、同じサイズと同じ範囲の値を持つからです。同じ記述が記録に適用されないのですか? –

+0

リンク先のページやコンパイラには該当しません。互換性リストには特に '互換性のある序数型'があり、 'myInt'と' myNewInt'はそうです; '宣言の同じ順序で同じフィールドと型を含む異なるユニットで定義されたレコード 'については何も言いません。 :)他の言語が 'namespaces'と呼ぶもののDelphi(緩やかな)サポートは、それらの名前空間で宣言された型間の型の差異を含みます。 –

+3

「構造型」(http://docwiki.embarcadero.com/RADStudio/en/StructuredTypes.html)の「レコード(伝統的)」セクションも参照してください。 'Variant Parts in Records'が始まる直前の最後のコードスニペットとそれに続く段落を見てください。具体的には、ローカライズされた 'var s:record ...'を定義し、 "この種の独立して宣言されたレコードは、構造が同一であっても代入互換ではありません"と述べています。レコードの宣言についての質問。 –