如何为2个集合使用相同的foreach代码?

Ade*_*ata 8 c# entity-framework

我有两个不同类型的2个集合,但几乎有相同的字段集.在一个函数中,我需要根据一个条件迭代其中一个集合.我想只编写一个代码块来覆盖这两种情况.示例:我有以下代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在:我想简化这段代码只使用相同的逻辑一次(因为它们是相同的),如下所示(PS:我知道下面的代码不正确,我只是在解释我想做的事情):

var typecollection = Condition1 ? Type1Collection : Type2Collection;

foreach(var typevar in TypeCollection)
{

   // the same code logic is used here
   typevar.Notes = "note";
   typevar.Price = 1;       
 }
Run Code Online (Sandbox Code Playgroud)

Type1和Type2的定义类似于以下代码(实际上它们是实体对象):

    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; }
    }
Run Code Online (Sandbox Code Playgroud)

更新1:

我在foreach块中包含了一些示例代码(我正在访问这两种类型的公共属性).

更新2:

我已经包含了示例Type1和Type2定义,因为您可以看到我在两个类中有2个常见的公共属性,我想在foreach块中更新.

更新3:

我很抱歉混淆,Type1和Type2派生自EntityObject(它们都是我的实体模型的一部分,Type1Collection和Type2Collection实际上是这两个实体的EntityCollection.

Sim*_*mon 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());
}
Run Code Online (Sandbox Code Playgroud)

或者,如果他们共享一个公共接口,您可以直接转换为该接口.您将保持类型安全

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());
}
Run Code Online (Sandbox Code Playgroud)

  • @DanielCastro我正在使用IEnumerable.这就是Cast的回报.我只在顶部添加了两个列表,使其成为可编译的代码. (2认同)

Edm*_*ppe 2

鉴于 Jon Skeet 暗示使用 LINQConcat方法以及 OP 声明所涉及的类是EntityObjects,这是另一种可能的解决方案。这假设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; }
}
Run Code Online (Sandbox Code Playgroud)

这允许 OP 声明具有公共属性的接口,并让他的EntityObject子类实现该接口:

public interface IMyType
{
    String Notes { get; set; }
    decimal Price { get; set; }
}
public partial class Type1 : IMyType {}
public partial class Type2 : IMyType {}
Run Code Online (Sandbox Code Playgroud)

而原来的代码就变成了:

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;
}
Run Code Online (Sandbox Code Playgroud)