通用foreach方法接受相同类型的列表和值,并更改列表成员属性



我有多个类带有同一属性的类。我想创建一个单个方法的单个方法。

示例:

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

正如预期的,我收到此错误:

'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?)

我试图找到一个有用的答案,但只能找到检索属性值而不是更改属性值的示例。任何建议都非常感谢。

创建一个称为 IIsSelected

的接口
public interface IIsSelected
{
   bool IsSelected { get; set; }
}

然后在具有IsSelected属性的类上实现此接口:

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

将您的方法更新为:

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

该方法仅将除了任何实现IIsSelected接口和编译器的类型都不会引发错误。

您可以使用Interface并装饰您的类以支持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);
    }
}

其他答案很棒,但是有时在某些情况下,您无法用接口装饰现有类。例如,

  • 类定义在第三方DLL中,
  • 您没有团队负责人的许可。

在这些情况下,将属性集移到您的功能外,将其作为lambda函数传递:

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

并以这种方式称呼:

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

这是用于重复使用代码的标准技术 - Linq和jQuery广泛使用。

最新更新