2017-04-16 16 views
2

私は次のコードの両方を試してみましたが、どちらも同じように動作するようです。ref Tインデクサとget/setインデクサの違いはありますか?

// Case 1: ref T indexer 
class Map { 
    Tile[,] tiles; 

    public ref Tile this[int x, int y] 
     => ref tiles[x, y]; 
} 

// Case 2: get/set indexer 
class Map { 
    Tile[,] tiles; 

    public Tile this[int x, int y] { 
     get => tiles[x, y]; 
     set => tiles[x, y] = value; 
    } 
} 

tilesがコンストラクタで初期化されていると、そのTilestructです。両者に顕著な違いはありますか? Tileclassの場合はどうなりますか?

+0

タイプが変更可能な場合のみ違いがあります –

+0

はい、大きな違いがあります。 TileにXプロパティを与え、map [0,0] .X = 42;を試してください。 –

+0

ありがとうございます。ケース2では、そのプロパティを変更することはできません。ありがとう、私は前者と行くつもりです。 :) – Dave

答えて

2

タイルがコンストラクタで初期化され、そのタイルが構造体であると仮定します。両者に顕著な違いはありますか?

CASE 1

// Case 1: ref T indexer 
class Map { 
    Tile[,] tiles; 

    public ref Tile this[int x, int y] 
     => ref tiles[x, y]; 
} 

あなたはそれを変更しても、別のオブジェクトに設定することができますので、あなたがインデックスさTitleオブジェクトへrefを戻ってきています。これはrefを返すことができるC#7.0の新機能で、タグ付きで保存しておくこともできます。換言すれば、は、値ではなく格納場所を返します。

保存場所を返すので、新しいTileオブジェクトをインデックス済みアイテムに完全に割り当てることができます。 refがなければ、それを変更することしかできません。

CASEここ2

class Map { 
    Tile[,] tiles; 

    public Tile this[int x, int y] { 
     get => tiles[x, y]; 
     set => tiles[x, y] = value; 
    } 
} 

は同じですが、簡潔にするためにC#7.0なしです:

class Case2MapWithoutCSharp7 
{ 
    Tile[,] tiles; 

    public Tile this[int x, int y] 
    { 
     get { return tiles[x, y]; } 
     set { tiles[x, y] = value; } 
    } 
} 

あなた指数、それはあなたがコピーを取得している場合になるときTileは、structあるので、これを試してみてください(TileはプロパティXとします):

map[0, 0].X = 10; 

エラーCS1612 'Case2MapWithoutCSharp7.this [int、int]'の戻り値は変数ではないため、変更できません。

コンパイラは、あなたが行っていると思っていること(インデックスされた項目を変更する)が実際にあなたがやっていることではないことを明示的に明確にしています。あなたは実際にコピーを修正しているので、正確にそれをする必要があります。だから、Xを設定することができるようにするには、このようなコピーでそれを実行する必要があります。

var tile = map[0, 0]; 
tile.X = 10; 

あなたはそのエラーhereの詳細を読むことができます。

タイルがclassの場合はどうなりますか?

最初のケースでは、保存場所を返すので、インデックス付きアイテムに新しいTileオブジェクトを完全に割り当てることができます。

refがない場合、classオブジェクトが参照渡しされるため、オブジェクトを変更できますが、新しいオブジェクト全体への参照は設定できません。だから、これを行うことができます:

map[0, 0].X = 2; 

をしかし、あなたは、このやった場合:

var tile = map[0, 0]; 
tile = new Tile(); 
tile.X = 5; 

をあなたは明らか真新しいTileはなく、あなたがインデックス1を変異されています。

関連する問題