【问题标题】:How to use an object of a generic class inside a generic class in C#?如何在 C# 中的泛型类中使用泛型类的对象?
【发布时间】:2020-07-08 07:33:42
【问题描述】:

我有一个通用类。而且这个泛型类需要有另一个与其成员相同的类的实例。

基本上,我正在尝试实现一系列操作。所以每个班级都必须知道下一项才能继续操作。

ChainedItem(Uri) -> ChainedItem(String) -> ChainedItem(MyClass) -> ....

这是我迄今为止尝试过的。

public abstract class ChainedItem<T>
{        
    private ChainedItem<R> m_chainedItem;

    public void SetNextChainedItem(ChainedItem<R> chainedItem)
    {
        m_chainedItem = chainedItem;
    }

    public abstract void DoOperation(T data);

    public virtual void ContinueNextOperation<R>(R data)
    {
        if(m_chainedItem != null)
            m_chainedItem.DoOperation(data);
    }
}

但我不能这样使用它,因为第 3 行中的 R 尚未定义。

【问题讨论】:

  • 你应该像public abstract class ChainedItem&lt;T, R&gt;这样声明你的类,使R在你的类中可用
  • 在我看来你正在寻找构建一个 Monad。迄今为止我为 c# 程序员找到的对 Monads 的最佳解释is this one.
  • 快速思考,使用 OOP 概念,引入 IChainable 之类的类或接口,添加 where T: IChainable 并使用具体接口 IChainable 代替 R。你所有的模型都需要实现这个接口,它会工作并且看起来很棒,希望^^。

标签: c# .net generics linked-list


【解决方案1】:

这实际上是不可能的,因为编译器不支持,否则它会导致编译器的堆栈溢出,这种事情是无穷无尽的,所以不可能,因为目前由更严格的 .NET 规范定义的泛型类型验证比 C++ 中的模板。

您可以使用 LinkedList&lt;ChainedItem&lt;&gt;&gt;,但菱形运算符因此在 C# 中不可用:

How to do generic polymorphism on open types in C#?

因此,也许您可​​以使用接口和类型检查来编写这样的东西,不包括空值:

public interface IChainedItem
{
  void DoOperation(object value);
}
public abstract class ChainedItem<T> : IChainedItem
{
  private IChainedItem m_chainedItem;

  public void SetNextChainedItem(IChainedItem chainedItem)
  {
    m_chainedItem = chainedItem;
  }

  public abstract void DoOperation(T data);

  public virtual void ContinueNextOperation(object data)
  {
    if ( m_chainedItem != null )
      m_chainedItem.DoOperation(data);
  }

  public void DoOperation(object value)
  {
    if ( value == null )
      throw new ArgumentNullException();
    var typeIn = value.GetType();
    var typeRequired = typeof(T);
    if ( typeIn != typeRequired )
    {
      string message = $"Bad type in ChainedItem.DoOperation(object): "
                     + $"{typeRequired.Name} is required and not {typeIn.Name}.";
      throw new ArgumentException(message);
    }
    DoOperation((T)value);
  }
}

【讨论】:

    【解决方案2】:

    你需要做这样的事情:

    Code fiddle

        public class Program
        {
           public static void Main()
           {
             var testObj1 = new ChainedItem<int, string>();
             var testObj2 = testObj1.GetNextChainedItem<bool>();
            
             Console.WriteLine(testObj1.GetType().ToString());
             Console.WriteLine(testObj2.GetType().ToString());
            
           }
       }
    
    
    
       public class ChainedItem<T,R>
    {        
        private object NextChainedItem;
        
        public ChainedItem<R,S> GetNextChainedItem<S>()
        {
            ChainedItem<R,S>NextChainedItem = new ChainedItem<R,S>();
            return NextChainedItem;
        }
        
        
       
    }
    

    【讨论】:

    • 我需要引用同一个类中的对象。例如,在您的代码中, private ChainedItem m_chainedItem;不会工作,因为 oSbject 未定义。
    • 将其定义为对象并进行显式转换来设置它
    猜你喜欢
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 2010-10-15
    • 2013-10-04
    相关资源
    最近更新 更多