2012-02-14 10 views
1

私はC#を教えてきましたが、私はカスタムデータ型の使い方を学んでいます。私が書いているプログラムは、一対の座標ペアを生成します。私は、各セット(x1、x2、y1、y2)を保持するデータ型を、そのセットに関連する他のいくつかの変数と一緒に作成することは理想的だと考えました。しかし、プログラムは複数の座標セット(異なるカテゴリ)の配列を生成するので、物事を追跡することはまだ困難です。私はそれをさらにカテゴリに分類し、それぞれのカテゴリを第3のレベルの第3のタイプとして配置し、それを第3レベルとしてリストに入れました。C#ランタイムでのカスタムデータ型の復帰の変更

アイテムの各「ティア」には、そのティア固有のプロパティがいくつかありますが、このロードブロックの前では、階層間でデータを交換する必要はありませんでした。問題は、オフセットを使用して座標ペアのセットを変更する必要があり、各オフセットが親データタイプに固有であることを認識したときに発生しました。オフセットをデータ型のクラス自体の外側から取得したものではなく、データとオフセットを返すようにget {}コードを変更できます(「スキュー」と呼ばれます)。親データ型(公的な静的なものでも)に値を設定しようとしましたが、何らかの理由で子がそれを読み取れませんでした。

私がこの作業を行う方法を知っている唯一の方法は、各座標セットでプロパティを設定することですが、何千ものあるかもしれません。この値は親に固有ですが、すべての子がそれを使用する必要があるため、他の多くの計算が行われるため、無駄に見えます。私の他の考えは、オフセット配列を維持し、値が取り出される場所に追加することでした。しかし、それはデータ型そのものの中にそれを含めるほどきれいではないので、混乱につながります。これを達成する別の方法がありますか?ここで

は、コードの一部がどのように見えるかです:あなたのコードで

public class SlotData 
    { 
     private double _x1, _x2, _y1, _y2; 

     public double X1 
     { 
      get { return _x1; } 
      set { _x1 = value; } 
     } 
     public double X2 
     { 
      get { return _x2; } 
      set { _x2 = value; } 
     } 
     public double Y1 
     { 
      get { return _y1; } 
      set { _y1 = value; } 
     } 
     public double Y2 
     { 
      get { return _y2; } 
      set { _y2 = value; } 
     } 
    } 
public class ClientInfo 
    { 
     public static double _skewX, _skewY; 

     public SlotGroup1 Group1 
     { 
      get; 
      set; 
     } 
     public SlotGroup2 Group2 
     { 
      get; 
      set; 
     } 
     public SlotGroup3 Group3 
     { 
      get; 
      set; 
     } 
    } 

public class SlotGroup1 
    { 
     public SlotData Slot1 
     { 
      get; 
      set; 
     } 
     public SlotData Slot2 
     { 
      get; 
      set; 
     } 
    } 

答えて

1
public class SlotData 
    { 
     private SlotData() { } 
     public SlotData(SlotGroupBase group) 
     { 
      this._group = group; 
     } 

     private SlotGroupBase _group; 

     public double X1 { get; set; } 
     public double X2 {get; set;} 
     public double Y1 {get; set;} 
     public double Y2 {get; set;} 

     public double NewX1 
     { 
      get 
      { 
       return _group.ClientInfo._skewX + X1; 
      } 
     } 
    } 

    public class ClientInfo 
    { 
     public double _skewX, _skewY; 

     public SlotGroup1 Group1 { get; set; } 
    } 

    public abstract class SlotGroupBase 
    { 
     private SlotGroupBase() { } 
     public SlotGroupBase(ClientInfo ci) 
     { 
      this._ci = ci; 
     } 

     private ClientInfo _ci; 

     public ClientInfo ClientInfo 
     { 
      get 
      { 
       return _ci; 
      } 
     }    
    } 

    public class SlotGroup1 : SlotGroupBase 
    { 
     public SlotGroup1(ClientInfo ci):base (ci) {} 
     public SlotData Slot1 { get; set; } 
     public SlotData Slot2 { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     ClientInfo ci = new ClientInfo(); 
     SlotGroup1 sg1 = new SlotGroup1(ci); 
     sg1.Slot1 = new SlotData(sg1); 
     sg1.Slot2 = new SlotData(sg1); 
     Console.ReadLine(); 
    } 

はあなたが親や子孫のデータ・タイプのいずれかを持っていません。したがって、ある型のメンバーは、ある種のオブジェクトのインスタンスへの参照を持つ以外の方法で、他の型にアクセスできませんでした。

しかし、オブジェクト指向のプログラミングが役に立ちます。 SlotGroupNタイプのそれぞれがClientInfoへの参照を持っている必要がある場合、ClientInfoへの参照を含む基本クラスSlotGroupBaseを持つことは価値があります。またタイプの参照をSlotGroupBaseに追加する必要があります。この場合、あなたは

return _group.ClientInfo._skewX + X1; 

のようなあなたのスキューにアクセスするもう一つの良いアイデアは、SlotGroupを参照することなく、ClientInfoを参照することなく作成SlotGroupNクラスのインスタンスからSlotDataクラスのアイテムを自分自身と他の開発者を制限することです。私は仕事であろうと、よりエレガント何も考えることができませんでした

using System.Drawing; 

public class SlotData 
{ 
    private PointF _one; 
    private PointF _two; 

    internal SizeF Skew {get; set;} 

    public PointF One 
    { 
     get 
     { 
      return PointF.Add(_one, Skew); 
     } 
     set {_one = value; } 
    } 

    public PointF Two 
    { 
     get 
     { 
      return PointF.Add(_two, Skew); 
     } 
     set {_two = value; } 
    } 
} 

public class SlotGroup : List<SlotData> 
{ 
    internal SizeF Skew 
    { 
     set 
     { 
      foreach(var slotData in this) 
      { 
       slotData.Skew = value; 
      } 
     } 
    } 
} 

public class ClientData : List<SlotGroup> 
{ 
    private SizeF _skew; 

    public SizeF Skew 
    { 
     get { return _skew; } 

     set 
     { 
      _skew = value; 
      foreach (var slotGroup in this) 
      { 
       slotGroup.Skew = value; 
      } 
     } 
    } 
} 

...あなたは、デフォルトのコンストラクタをプライベートにして、パラメータClientInfo

public SlotGroupBase(ClientInfo ci) 
+0

ああ、問題は私が実際にそれを子供にしていないことです。 Intellisenseはこれを階層構造として表示しているため、これは私がやっていることだと思っていました。しかし、スコープ内にあるものにアクセスできない場合は、間違って実装している可能性があります。私は暗黙のget/setを積み重ねる方法も好きです。私がやっていたことよりもうまく見えます。これは私が想像しているのとまったく同じように機能し、他のデータのCPU時間が増えるようになります。お手伝いいただきありがとうございます。 – Zatronium

0

あなたは設計の拡張で、コンストラクタを追加する必要があり、これを達成するために。カプセル化は、含まれているクラスがそのコンテナのデータにアクセスすることができず、コンテナクラスの子アクセサをオーバーライドするコードがより煩雑になるはずである。

+0

私はあなたが提案したソリューションを使用するとは思わない、主に私は不要な反復を取り除きたいからです。しかし、新しいデータ型を作成するのではなく、サブクラスを追加するためにリストクラスを継承する方法が好きです。グループには常に同じ変数があるわけではないので、少し調整する必要があるかもしれませんが、一般的な考え方は良いものです。 – Zatronium

+0

@ザトロンニウム、私はあなたに反復について指摘しますが、コンテナが各コンテナの値を設定するか、各コンテナがコンテナから値を読み取るか、独自のアクセサーと列挙子を実装する必要があります。それらの実装でスキューを実行します。私は最後の選択肢に誘惑されましたが、コードがはるかに複雑であると感じました。 – Jodrell

+0

浪費されているようには思えませんが、私のポストではコードを大幅に短縮しました。グループごとに4〜100以上のスロット、3〜20以上のグループがあり、ユーザーは複数のクライアントを起動することができます(データはクライアントごとではなくユーザーごとに保存されます)。だから、リストをベースとしてどのように使ったかが好きだと言った理由は、柔軟性が増したからです。しかし、最終的に私は実行時間を低く抑えたいので質問をしたので、プログラムは配列の変更を待っていません。両方の回答が助けられたので、私は両方を上げるつもりでしたが、私の口座は新しくなりました。私はより多くの担当者を持っているときにそれを行うでしょう。 – Zatronium

関連する問題