c# - 如何编写 C# 方法来返回基于枚举参数的 Func<T> ?

标签 c# generics observablecollection generic-collections

我有一组方法,每个方法都返回各种类型 T 的 ObservableCollection,并且希望能够编写一个基于发送的枚举值返回这些方法的工厂方法。例如,假设我有以下高度现实的方法...

public ObservableCollection<Gribble> GetGribbles() {
  return new ObservableCollection<Gribble>();
}

public ObservableCollection<Gribulator> GenerateGribulators() {
  return new ObservableCollection<Gribulator>();
}

public ObservableCollection<Knepple> MakeKnepples() {
  return new ObservableCollection<Knepple>();
}

...以及以下枚举...

public enum ListNames {
  Gribbles,
  Gribulators,
  Knepple
}

那么我希望能够做到这一点...

Func<ObservableCollection<Gribble>> someGribbles = 
       MakeFunc<Gribble>(ListNames.Gribbles);

原因是我有一个带有这样签名的帮助器类...

public void GetList<T>(ListNames listName, 
  Func<ObservableCollection<T>> serviceCall, 
  Action<ObservableCollection<T>> handleList)

serviceCall是获取列表的方法,handleList是回调方法。目前,无论何时调用此方法,代码都必须传递获取列表的实际函数。

然而,这被证明是一个糟糕的设计选择,因为这意味着如果代码的两部分都为特定列表调用 GetList,它们可能会传入两个不同的服务调用,这将导致结果不一致。我想将服务调用封装在 MakeFunc 方法中,该方法将从 GetList 调用,这意味着使用 GetList 的代码永远不会看到实际的服务调用,因此不会做任何错误。

我已经尝试了一些东西,但正在努力获得任何可以编译的东西。我得到的最接近的是以下...

public Func<ObservableCollection<T>> MakeFunc<T>(ListNames listName) {
  switch (listName) {
    case ListNames.Gribbles:
      return GetGribbles;
    case ListNames.Gribulators:
      return GenerateGribulators;
    case ListNames.Knepple:
      return MakeKnepples;
    default:
      throw new ArgumentException("Unknown list name");
  }
}

...但这会导致编译器错误,类似于“GetGribbles() 有错误的返回类型”,以及当我将鼠标悬停在 MakeFunc 方法中的 GetGribbles 上时弹出的工具提示说

Expected a method with 'ObservableCollection<T> GetGribbles()' signature

可以做我想做的事吗?如果是这样,有人能解释我做错了什么吗?

如果有什么不同的话,我在 Visual Studio 2010 中使用 C# 4.0。

最佳答案

如果 GribbleGribulatorKnepple 类共享公共(public)基类型或实现公共(public)接口(interface),那么您可以这样做:

public Func<ObservableCollection<ICommonInterface>> MakeFunc(ListNames listName) 
{
   ...
}

如果它们没有共同的基本类型或接口(interface),您必须这样做:

public Func<ICollection> MakeFunc(ListNames listName) 
{
   ...
}

诚然,这不是一个很好的解决方案。注意:您可以将 ICollection 替换为 INotifyCollectionChanged 或您最需要的任何非通用接口(interface)。

在这两种情况下,您都必须依赖调用者来指定数据类型(即使调用者也指定了枚举值)。因此,您也可以摆脱枚举,并进行如下操作:

public Func<ObservableCollection<T>> MakeFunc<T>() 
{
  if (typeof(T) == typeof(Gribble))
      return () => GetGribbles() as ObservableCollection<T>;
  if (typeof(T) == typeof(Gribulator))
      return () => GenerateGribulators() as ObservableCollection<T>;
  if (typeof(T) == typeof(Knepple))
      return () => MakeKnepples() as ObservableCollection<T>;
  throw new ArgumentException("Unknown list name");
}

然后调用者可以简单地写:

var gribblesFunc = MakeFunc<Gribble>();

关于c# - 如何编写 C# 方法来返回基于枚举参数的 Func<T> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17225595/

相关文章:

c# - 以 float 作为参数的 ScrollEventArgs 构造函数

c# - 提高大型结构列表的二进制序列化性能

listview - Xamarin ListView 绑定(bind)到 ObservableCollection 随机更改

c# - 如何添加 ObservableCollection<Class<T>> 为 T 使用继承

c# - 对 ObservableCollection 进行排序时出现 InvalidOperationException

c# - 如何在 C# 中将 12 位整数转换为十六进制字符串?

c# - 我应该在这里使用 static 吗?

c# - 返回一个新实例而不是泛型中的空实例

java - Gson 类强制转换异常

java - 在 Java 中将泛型类型与枚举相关联