8

I am trying to move some code that I wrote to a more generic method. While the method is longer, the part I am having trouble with is the following :

public static void Test()

{    
           MyObjectType[] list1 = ListMyObjectTypeMethod1();
            MyObjectType[] list2 = ListMyObjectTypeMethod2();

            List<MyObjectType> linqAblelist1 = new List<MyObjectType>(list1);
            List<MyObjectType> linqAblelist2 = new List<MyObjectType>(list2);

            IEnumerable<MyObjectType> toBeAdded = linqAblelist1.Where(x => linqAblelist2.All(y => y.Property1 != x.Property1));
            IEnumerable<MyObjectType> toBeDeleted = linqAblelist2.Where(a => linqAblelist1.All(b => b.Property1 != a.Property1));

}

And I am trying to pass in a generic type for MyObjectType, but where I have [How To Set Property Here?] how does one specify that in a parameter for the method?

public static void Test<T>(T[] x, T[] y)
        {
            List<T> list1 = new List<T>(x);
            List<T> list2 = new List<T>(y);
            IEnumerable<T> toBeAdded = list1.Where(x => list2.All(y => y.[How To Set Property Here?] != x.[How To Set Property Here?]));
            IEnumerable<T> toBeDeleted = list2.Where(a => list1.All(b => b.[How To Set Property Here?])); != a.[How To Set Property Here?]));));

        }
user3010406
  • 541
  • 2
  • 8
  • 22

4 Answers4

12

Pass in the selection of the property as a Func<T, TProperty>:

public static void Test<T, TProperty>(T[] x, T[] y, Func<T, TProperty> propertySelector)
    {
        List<T> list1 = new List<T>(x);
        List<T> list2 = new List<T>(y);
        IEnumerable<T> toBeAdded = list1.Where(x => list2.All(y => !propertySelector(y).Equals(propertySelector(x))));
        IEnumerable<T> toBeDeleted = list2.Where(a => !list1.All(b => propertySelector(b).Equals(propertySelector(a))));

    }

Then you can call it by specifying a lambda expression for propertySelector:

Test(someArray, someOtherArray, t => t.SomeProperty);
Anders Abel
  • 67,989
  • 17
  • 150
  • 217
  • This would get around having to have an interface constraint. +1 Good idea. – Jared Nov 19 '13 at 20:21
  • I get a cannot apply operator compiler error with this code. Exact error is cannot apply operator between TProperty and TProperty. – user3010406 Nov 19 '13 at 23:25
1

The best option is to introduce a generic type constraint that will make sure T either inherits from a specific class or implements an interface. In either case the class or interface have to declare Property1. E.g. like this:

public static void Test<T>(T[] x, T[] y) where T : IHasProperty1
{
    …
}
Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
0

You need to put some constraints on your generic type.

public static void Test<T>(T[] x, T[] y) where T : <SomeInterface>
{
   List<T> list1 = new List<T>(x);
   List<T> list2 = new List<T>(y);
   IEnumerable<T> toBeAdded = list1.Where(x => list2.All(y => y.PropertyName != x.PropertyName));
    IEnumerable<T> toBeDeleted = list2.Where(a => list1.All(b => b.PropertyName)); != a.PropertyName));));

}
Jared
  • 2,736
  • 1
  • 18
  • 23
0

You cann add a generic constraint that will ensure that T will have the properties you're expecting. Some thing like:

public static void Test<T>(T[] x, T[] y) where T : MyObjectType
{
    List<T> list1 = new List<T>(x);
    List<T> list2 = new List<T>(y);
    IEnumerable<T> toBeAdded = list1.Where(x => list2.All(y => y.Property1  != x.Property1 ));
    IEnumerable<T> toBeDeleted = list2.Where(a => list1.All(b => b.Property1 )); != a.[How To Set Property Here?]));));

}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • Might as well just get rid of the generics if you are going to constrain T to being an implementation of the object. – Jared Nov 19 '13 at 22:45