2

我实际上想要做的是编写一个函数,允许我更改 DataGridView 中的选择,我想编写一个函数并将其用于行和列。这是一个简单的示例,它取消选择所有内容并选择新的行或列:

private void SelectNew<T>(T collection, int index) where T : IList
{
  ClearSelection();
  collection[index].Selected = true;
}

我的问题是这不起作用,因为它无法派生.Selected()可用,因为这是非通用 IList。

使用

where T : IList<DataGridViewBand>

会很好,但由于 DataGridViewRowCollection (和 -Column- )只是从 IList 派生的,所以这是行不通的。

在 C++ 中,我可能会使用特征成语。有没有办法在 C# 中做到这一点,还是有更惯用的方法?

4

3 回答 3

5

虽然理论上可以使用反射来做到这一点;因为您的明确目标只是处理行或列,所以最简单的选择是为函数创建两个重载:

private void SelectNew(DataGridViewColumnCollection collection, int index)
{
    ClearSelection();
    collection[index].Selected = true;
}

private void SelectNew(DataGridViewRowCollection collection, int index)
{
    ClearSelection();
    collection[index].Selected = true;
}

如果您尝试使用反射来执行此操作,它会起作用,但它会更慢,可读性更低,并且有没有编译时保护的危险;人们将能够传入其他类型的没有Selected属性的列表,它会编译并在运行时失败。

于 2013-06-24T16:35:00.440 回答
1

一种可能性是使用dynamic

private void SelectNew(IList collection, int index)
{
  ClearSelection();
  ((dynamic)collection)[index].Selected = true;
}

或者:

private void SelectNew(IList collection, int index)
{
  ClearSelection();
  DataGridViewBand toSelect = ((dynamic)collection)[index];
  toSelect.Selected = true;
}

这样做的最大缺点是你失去了编译时类型的安全性,所以我不推荐这样做,除非它可以防止大量的代码重复。

(第二个版本具有更多的编译时类型安全性,但代价是更加冗长和明确。)

于 2013-06-24T17:59:53.353 回答
0

如果您有一个实现 的集合IEnumerable,并且您提前知道它包含什么类型的元素,则可以执行以下操作:

IList<DataGridViewBand> typedCollection = collection
                                          .Cast<DataGridViewBand>()
                                          .ToList();

这将允许您调用通用扩展方法:

private void SelectNew<T>(T collection, int index)
   where T : IList<DataGridViewBand>
{
  ClearSelection();
  collection[index].Selected = true;
}

typedCollection.SelectNew(1);

编辑:

如果您决定要限制 T on IList<DataGridViewBand>,您不妨直接为该类型编写一个方法,因为使用泛型您什么也得不到。

IList<DataGridViewBand> typedCollection = collection
                                          .Cast<DataGridViewBand>()
                                          .ToList();

private void SelectNew(IList<DataGridViewBand> collection, int index)
{
  ClearSelection();
  collection[index].Selected = true;
}

typedCollection.SelectNew(1);
于 2013-06-24T18:05:28.993 回答