繁体   English   中英

在泛型方法中返回特定类型,具体取决于运行时没有反射或动态的枚举值

[英]Return specific type in generic method depending on enum value without Reflection or dynamic during runtime

我有一个非泛型IList ,我想在运行时根据enum值进行转换。

我无法在实现中更改非泛型 IList 的类型,因为它是库代码。

我也不想使用反射(因为它很慢)或动态关键字(因为它不安全并且可能导致错误)。

在库代码中有以下 class:

public class ListView //THIS IS LIBRARY CODE AND CAN NOT BE CHANGED
{
  public IList itemsSource { get; set; }
}

然后在继承自 ListView 的 CustomListView class 中,我想根据 ItemType 将 itemsSource 转换为适当的 class。

另一个限制是 CustomListView 不能是通用的(由我们使用的库决定)

public class CustomListView : ListView
{
    public dynamic GetItems()
    {
        switch (ItemType)
        {
            case ItemType.A:
              return itemsSource.Cast<A>().ToList();
            case ItemType.B:
              return itemsSource.Cast<B>().ToList();
            default:
              throw new InvalidOperationException("Not supported");
        }
    }
}

但我希望它直接返回正确的类型,而不是使用动态。

类似的东西(下面的代码不起作用:):

public IList<T> GetItems(ItemType itemType) //The type of T should change depending on what i return
{
    switch (ItemType)
    {
        case ItemType.A:
          return itemsSource.Cast<A>().ToList();
        case ItemType.B:
          return itemsSource.Cast<B>().ToList();
        default:
          throw new InvalidOperationException("Not supported");
    }
}

我将如何实施?

编辑/附加

正如你们指出的,我应该澄清一些事情。

Class A 和 B 确实具有相同的基础 class。 但我希望能够不再从基本类型中转换它(因为我已经在 GetItems() 方法中转换它并且 ItemType 的值也是已知的)。

我希望能够做到以下几点

IList<A> aItems = listView.GetItems()

无需铸造。

想想如何使用这个方法:

ItemType itemType = ...;
var x = listView.GetItems(itemType);

itemType的值可以是A ,也可以是B 那么x的类型应该是什么? 它是IList<A>IList<B> ,表达这一点的唯一方法是使用IList<A>IList<B>都继承自的类型,这将我们带回到IList 如果您在编译时不知道您想要的类型,那么尝试将返回类型更改为更具体的东西没有多大意义,因为您将无法在没有反射的情况下访问它作为更具体的类型。

如果您在编译时确实知道所需的类型,则提供返回所需类型的方法的重载:

public IList<A> GetAItems() { ... }
public IList<B> GetBItems() { ... }

您希望如何使用这种方法? 类型参数由方法的调用者设置。 无法从方法中设置类型参数。 请说明用途。

你可以试试这些:

IList<T> GetItems<T>(ItemType itemType)
{
    switch (itemType)
    {
        case ItemType.A:
          return (IList<T>)(IList)(itemsSource.Cast<A>().ToList());
        case ItemType.B:
          return (IList<T>)(IList)(itemsSource.Cast<B>().ToList());
        default:
          throw new InvalidOperationException("Not supported");
    }
}
IList GetItems(ItemType itemType)
{
    switch (itemType)
    {
        case ItemType.A:
          return itemsSource.Cast<A>().ToList();
        case ItemType.B:
          return itemsSource.Cast<B>().ToList();
        default:
          throw new InvalidOperationException("Not supported");
    }
}

或者,正如@Qwertyluk 在评论中所建议的那样,如下所示:

private IList<object> GetItems(ItemType itemType)
{
    
    switch (itemType)
    {
        case ItemType.A:
        case ItemType.B:
          return itemsSource.Cast<object>().ToList();
        default:
          throw new InvalidOperationException("Not supported");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM