8

2 つの異なるタイプの 2 つのコレクションがありますが、フィールドのセットはほぼ同じです。1 つの関数で、1 つの条件に応じてコレクションの 1 つを反復処理する必要があります。両方のケースをカバーするコード ブロックを 1 つだけ書きたいと思います。例: 次のコードがあります。

if (condition1)
{
    foreach(var type1var in Type1Collection)
    {

    // Do some code here
       type1var.Notes = "note";
       type1var.Price = 1;
    }
}
else
{
    foreach(var type2var in Type2Collection)
    {

    // the same code logic is used here
       type2var.Notes = "note";        
       type2var.Price = 1;
    }
}

今:このコードを単純化して、同じロジックを1回だけ使用するようにします(それらは同一であるため)、次のようなものです(PS:次のコードが正しくないことはわかっています。やりたいことを説明しているだけです):

var typecollection = Condition1 ? Type1Collection : Type2Collection;

foreach(var typevar in TypeCollection)
{

   // the same code logic is used here
   typevar.Notes = "note";
   typevar.Price = 1;       
 }

Type1 と Type2 の定義は次のコードのようになります (実際には Entity オブジェクトです)。

    public class Type1 : EntityObject
    {
        public int Type1ID { get; set; }
        public int Type1MasterID { get; set; }

        public String Notes { get; set; }
        public decimal Price { get; set; }
    }

    public class Type2 : EntityObject
    {
        public int Type2ID { get; set; }
        public int Type2MasterID { get; set; }

        public String Notes { get; set; }
        public decimal Price { get; set; }
    }

更新 1:

foreach ブロック内で使用しているサンプル コードをいくつか含めました (2 つの型のパブリック プロパティにアクセスしています)。

更新 2:

サンプルの Type1 と Type2 の定義を含めました。両方のクラスに、foreach ブロックで更新したい 2 つの共通のパブリック プロパティがあることがわかります。

更新 3:

混乱して申し訳ありませんが、Type1 と Type2 は EntityObject から派生しています (どちらも私のエンティティ モデルの一部であり、Type1Collection と Type2Collection は実際にはこれら 2 つのエンティティの EntityCollection です。

4

6 に答える 6

9

動的に使用できます。型安全性が失われることに注意してください。

var list1 = new List<bool>(){true,false};
var list2 = new List<int>(){1,2};

var typecollection = condition1 ? list1.Cast<dynamic>() : list2.Cast<dynamic>();
foreach (var value in typecollection)
{
    //then you can call a method you know they both have
    Debug.WriteLine(value.ToString());
}

または、共通のインターフェースを共有している場合は、それに直接キャストできます。型の安全性を維持します

var list1 = new List<bool>(){true,false};
var list2 = new List<int>(){1,2};

var typecollection = condition1 ? list1.Cast<IConvertible>() : list2.Cast<IConvertible>();
foreach (IConvertible convertible in typecollection)
{
    //we now know they have a common interface so we can call a common method
    Debug.WriteLine(convertible.ToString());
}
于 2013-01-26T05:16:49.133 に答える
2

LINQ のConcatメソッドを使用するという Jon Skeet のヒントと、関連するクラスがEntityObjects であるという OP のステートメントを考えると、別の解決策が考えられます。これは、サブクラスが部分クラスEntityObjectとして定義されていることを前提としています。

public partial class Type1 : EntityObject
{
    public int Type1ID { get; set; }
    public int Type1MasterID { get; set; }
    public String Notes { get; set; }
    public decimal Price { get; set; }
}

public partial class Type2 : EntityObject
{
    public int Type2ID { get; set; }
    public int Type2MasterID { get; set; }

    public String Notes { get; set; }
    public decimal Price { get; set; }
}

これにより、OP は共通のプロパティを持つインターフェイスを宣言し、そのEntityObjectサブクラスにそのインターフェイスを実装させることができます。

public interface IMyType
{
    String Notes { get; set; }
    decimal Price { get; set; }
}
public partial class Type1 : IMyType {}
public partial class Type2 : IMyType {}

元のコードは次のようになります。

var query = (
    from type1var in type1Collection
    where condition1
    select (IMyType)type1var
   ).Concat(
    from type2var in type2Collection
    where !condition1
    select (IMyType)type2var
   );
foreach(var myType in query)
{
    myType.Notes = "note";
    myType.Price = 1;
}
于 2013-01-28T16:56:49.387 に答える
0

これはそれを行うのにあまり良い方法ではありませんが、少なくともうまくいくでしょう。

        var type1Collection = new Collection<Type1>();
        var type2Collection = new Collection<Type2>();

        var condition1 = new Random().Next(0, 2) != 0;

        dynamic selectedCollection;
        if (condition1)
            selectedCollection = type1Collection;
        else
            selectedCollection = type2Collection;

        foreach (var typeVar in selectedCollection)
        {
            typeVar.Notes = "note";
            typeVar.Price = 1;
        }
于 2013-01-26T15:47:50.927 に答える
0

私はまだ誰も拡張メソッドを提案していないことに驚いています:

public interface IMyType
{
    String Notes { get; set; }
    decimal Price { get; set; }
}

public static class MyTypeExtensions
{
    public static void MyLogic(this IMyType myType)
    {
        // whatever other logic is needed
        myType.Notes = "notes";
        myType.Price = 1;
    }
 }

これで、元の型を実装するだけで済みますIMyType:

public class Type1 : IMyType
{
    public int Type1ID { get; set; }
    public int Type1MasterID { get; set; }

    public String Notes { get; set; }
    public decimal Price { get; set; }
}

public class Type2 : IMyType
{
    public int Type2ID { get; set; }
    public int Type2MasterID { get; set; }

    public String Notes { get; set; }
    public decimal Price { get; set; }
}

次に、元のコードは次のようになります。

if (condition1)
{
    foreach (var type1 in type1Collection)
    {
        type1.MyLogic();
    }
}
else
{
    foreach (var type2 in type2Collection)
    {
        type2.MyLogic();
    }
}
于 2013-01-26T19:14:57.577 に答える
0

Dictionary に格納されている Predicate と Action を使用して実行できます。コード スニペットが何も返さないように見えるので、ここで Action を提案します。

public class IterationExample
{
    private readonly Dictionary<bool, Action> dictionary;

    public IterationExample()
    {
        dictionary = new Dictionary<bool, Action> { { true, CollectionOneIterator }, { false, CollectionTwoIterator } };
    }

    public void PublicMethod()
    {
        dictionary[condition]();
    }

    private void CollectionOneIterator()
    {
        foreach (var loopVariable in Type1Collection)
        {
            //Your code here
        }
    }

    private void CollectionTwoIterator()
    {
        foreach (var loopVariable in Type2Collection)
        {
            //Your code here
        }

    }
}

このようにして、コードの可読性とテスト容易性が向上し、長いメソッドを回避できます。

編集:

public class Entity
{
    public IList<string> Type1Collection { get; set; }
    public IList<string> Type2Collection { get; set; } 
}

public class ConsumingClass
{
    public void Example()
    {
        var entity = new Entity();
        entity.PublicMethod();
    }
}

public static class IterationExample
{
    private static readonly Dictionary<bool, Action<Entity>> dictionary;

    static IterationExample()
    {
        dictionary = new Dictionary<bool, Action<Entity>> { { true, CollectionOneIterator }, { false, CollectionTwoIterator } };
    }

    public static void PublicMethod(this Entity entity)
    {
        dictionary[condition]();
    }

    private static void CollectionOneIterator(Entity entity)
    {
        foreach (var loopVariable in entity.Type1Collection)
        {
            //Your code here
        }
    }

    private static void CollectionTwoIterator(Entity entity)
    {
        foreach (var loopVariable in entity.Type2Collection)
        {
            //Your code here
        }
    }
}
于 2013-01-26T05:18:25.270 に答える
0

2 つのクラス間で共通のプロパティをグループ化する type1 と type2 の基本型を作成できます。

class MyBaseType {
   // Common properties
}

class Type1 : MyBaseType {
   // Specific properties
}

class Type2 : MyBaseType {
   // Specific properties
}

次に、次のようなことができます。

IEnumerable<MyBaseType> collection;
if(condition1)
   collection = type1Collection;
else
   collection = type2Collection;

foreach(MyBaseType element in collection) {
   // Common logic
}

編集: サイモンがコメントで指摘しているように、十分な場合は基本型の代わりにインターフェイスを使用する必要があります (つまり、両方の型に特定の実装は必要ありません)。

于 2013-01-26T05:20:24.547 に答える