代码之家  ›  专栏  ›  技术社区  ›  Jules

具有仅对某些类型参数有效的方法的泛型类

  •  0
  • Jules  · 技术社区  · 16 年前

    假设你正在编写一个库来在屏幕上显示内容,所以你创建了一个 IDisplayable 界面。此接口有一种从对象创建控件的方法: displayable.GetControl() .

    您想创建可以显示的自己的列表类型: MyList<T> T 是一个 IDispleable 始终实现IDispleable,但如果您尝试调用 GetControl() 如果T不可IDisplay,但我想知道是否有静态类型安全的方法来实现它。可以做到吗?还是我看到了错误的解决方案?

    编辑:

    MyDisplayableList<T> : MyList<T> (where T : IDisplayable) .

    5 回复  |  直到 16 年前
        1
  •  5
  •   Mehrdad Afshari    16 年前

    public class MyList<T> : IList<T>
    {
        ...
    }
    
    public class MyDisplayableList<T> : MyList<T> where T : IDisplayable
    {
        ...
    }
    
        2
  •  8
  •   Thomas Levesque    16 年前

    IDisplayable 如果不是,扔一个 InvalidOperationException :

    if (!typeof(IDisplayable).IsAssignableFrom(typeof(T))) 
        throw new InvalidOperationException();
    

    或者,如果你有一个实例 T ,只需检查一下:

    IDisplayable disp = instanceOfT as IDisplayable;
    if (disp == null)
        throw new InvalidOperationException();
    // do stuff with `disp`.
    

    不过,你的设计可能有缺陷。你可能在一个类中放得太多,违反了单一责任原则。请先重新检查您的设计。

        3
  •  1
  •   dtb    16 年前

    你需要仿制药吗?

    我猜你有多个类在实现 IDisplayable 并希望将它们的所有实例放在同一个列表中。所以你只需要一个

    public class MyList : Collection<IDisplayable>, IDisplayable
    {
        public void GetControl()
        {
            foreach (IDisplayable displayable in this)
            {
                displayable.GetControl();
            }
        }
    }
    

    如果你真的想把非- IDispleable 在该列表中的实例中,找到公共基类并定义

    public class MyList2 : Collection<object>, IDisplayable
    {
        public void GetControl()
        {
            foreach (IDisplayable displayable in this.OfType<IDisplayable>())
            {
                displayable.GetControl();
            }
        }
    }
    
        4
  •  1
  •   tvbusy    16 年前

    我认为你想要的原因 MyList<T> 能够同时与两者合作 IDisplayable 和非- IDispleable 是因为有一些重复的功能。

    我建议您将基础实现作为 MyListBase<T> 它实现了列表执行的基本功能。然后你让MyDisplayableList继承MyList( MyDisplayableList<T> : MyList<T> where T : IDisplayable ),它仅执行IDispleable特有的功能。

    如果有任何特定于非IDisplay的函数,请添加 NonDisplayableList<T> : MyListBase<T> 以执行这些功能。

        5
  •  1
  •   Jordão    16 年前

    composite IDisplayable s.这正是ASP中控件建模的方式。NET或Windows窗体。

    public class CompositeDisplayable : IDisplayable {
    
      public void Add(IDisplayable displayable) {
        // TODO: check for null, cycles, etc...
        _list.Add(displayable);
      }
    
      public void Remove(IDisplayable displayable) {
        // TODO: check for null
        _list.Remove(displayable);
      }
    
      public Control GetControl() {
        var control = new Control(); 
        // this assumes Control is also a composite type
        _list.ForEach(displayable => control.Add(displayable.GetControl()));
        return control;
      }
    
      private List<IDisplayable> _list = new List<IDisplayable>();
    
    }
    

    然后,为了在你的“something”集合和组合之间架起桥梁,你可以创建一个这样的扩展方法:

    public static class DisplayableExtensions {
    
      public static IDisplayable ToDisplayable(this IEnumerable source) {
        if (source == null) throw new NullReferenceException(); // extension method should behave like instance methods
        var result = new CompositeDisplayable();
        source.
          OfType<IDisplayable>().
          ToList().
          ForEach(displayable => result.Add(displayable));
        return result;
      }
    
    }