Jack
Jack

Reputation: 996

Generic ForEach Method that accepts a List and Value of same Type and Changes List Member Properties

I have multiple classes with the same property. I want to create a single method that would serve the same purpose for each individual class.

Example:

 private void RefreshSelection<T>(ObservableCollection<T> itemList, T selectedItem)
    {
        foreach (var item in itemList)
        {
            item.IsSelected = selectedItem.Equals(item);
        }
    }

As expected, I recieve this error:

'T' does not contain a definition for 'IsSelected' and no extension method 'IsSelected' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)

I have tried to find a useful answer but can only find examples of retrieving the property value, not changing it. Any advice is greatly appreciated.

Upvotes: 0

Views: 53

Answers (3)

user1023602
user1023602

Reputation:

The other answers are great, but occasionally there are situations where you cannot decorate existing classes with an interface. For example,

  • the class definitions are in 3rd-party DLLs,
  • you do not have permission from the team leader.

For these situations, move the property-set outside your function, passing it in as a lambda function instead:

private void RefreshSelection<T>(ObservableCollection<T> itemList, T selectedItem,
                                 Action<T, bool> setSelected)
{
    foreach (T item in itemList)
    {
        setSelected(item, selectedItem.Equals(item));
    }
}

and call it this way:

RefreshSelection(itemList, selectedItem, (i, newValue) => 
{
    i.IsSelected = newValue;
});

This is a standard technique for reusing code - extensively used by Linq and jQuery.

Upvotes: 1

TheGeneral
TheGeneral

Reputation: 81493

You could use an Interface and decorate your classes that support IsSelected

public interface ISelectable
{
    bool IsSelected { get; set; }
}

public class MyAwesomeClass : ISelectable
{
    public bool IsSelected { get; set; }

    // Blah
}

private void RefreshSelection<T>(ObservableCollection<ISelectable> itemList, T selectedItem) 
    where T : class, ISelectable
{
    foreach (var item in itemList)
    {
        item.IsSelected = selectedItem.Equals(item);
    }
}

Upvotes: 1

Brownish Monster
Brownish Monster

Reputation: 732

Create an interface called IIsSelected

public interface IIsSelected
{
   bool IsSelected { get; set; }
}

Then implement this interface on your classes which has the IsSelectedproperty:

public class MySelectableClass : IIsSelected
{
    public bool IsSelected { get; set; }
}

Update your method to:

private void RefreshSelection<T>(ObservableCollection<T> itemList, T selectedItem)
where T: IIsSelected
{
    foreach (var item in itemList)
    {
        item.IsSelected = selectedItem.Equals(item);
    }
}

The method will only except any type which implements the IIsSelected interface and the compiler won't throw an error.

Upvotes: 1

Related Questions