【问题标题】:C# interfaces and genericsC# 接口和泛型
【发布时间】:2013-04-23 18:46:38
【问题描述】:

我对泛型(即T)在 C# 中的工作方式感到困惑。除非我弄错了,否则它的行为似乎与 C++ 不同。我正在尝试为数据网关创建一个简单的接口:

编辑已更新以匹配答案。 Visual Studio 现在抱怨派生类没有实现接口方法。

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable();
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable() { }
}

我不知道会传递什么类型,这就是我尝试使用泛型的原因。

【问题讨论】:

  • 试试public class LibraryGateway : IDataGateway&lt;Media&gt;
  • VS 抱怨使用带有类型参数的非泛型类型 IDataGateway。
  • 您是否正在尝试创建一个不知道实现者使用的类型的接口,或者您想使用泛型类型来实现?
  • 是的,阅读所有答案我一定混淆了通用的范围。通用的接口似乎合乎逻辑!
  • 我认为有两个可能的原因:首先,你的类实现中有一个带有小写 r 的“Updaterow”——大小写不匹配可能是导致它失败的原因。其次,就像我在回答中所说的那样,我认为您的 GetTable() 方法的定义有点偏离 - 您的界面中有 GetTable(T table),但从您的类中的实现来看,看起来您没有t 实际上希望它接受任何参数。

标签: .net generics interface


【解决方案1】:

您正在单独声明每个方法的类型参数。您应该在接口类型本身上声明它。

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable() { }
}

为了澄清,您当前的实现可以重写为:

public interface IDataGateway
{
    void InsertRow<T>(T row);
    void UpdateRow<U>(U row);
    IEnumerable<V> GetTable(V table);
}

也就是说,T 不需要与UV 相同。每个方法都由自己的类型参数泛化,但包含的接口类型本身不是泛型的。

通过在类型本身上声明类型参数,您可以将方法的类型参数限制为在由子类实现时相同。在您似乎熟悉的 C++ 术语中,您当前的实现类似于三个单独的模板函数,而我的实现更类似于模板类。

【讨论】:

  • 很好的解释谢谢。你说得对,在 C++ 中我更关注模板方法。
  • 我不明白为什么需要拆分通用参数类型。您将插入一种类型的行但更新另一种?
【解决方案2】:

您似乎正在尝试创建和实现一个通用接口,而不是通用方法。

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable(Media table) { }
}

当您有一个泛型方法(如原始问题中所示)时,这意味着可以使用任何类型的参数调用单个实现(例如LibraryGateway.InsertRow) - 仅在运行时才知道。但是,当您实现一个通用接口时,您可以参数化该接口,以便LibraryGateway.InsertRow 专门对Media 类型的项目进行操作。 IDataGateway&lt;T&gt; 的其他实现可能对其他类型进行操作,但 LibraryGateway 仅对 Media 对象进行操作。

【讨论】:

    【解决方案3】:

    从您的示例中,我认为最好的方法是使接口本身通用,而不是其中的方法:

    public interface IDataGateway<T>
    {
      void InsertRow(T row);
      void UpdateRow(T row);
      IEnumerable<T> GetTable(T table); // ???
    }
    

    我认为您的GetTable() 方法也需要修复——如果T 是表中包含的对象的类型,那么它(可能!)也不是表的类型。也许你的意思是IEnumerable&lt;T&gt; GetTable();

    那么你可以这样做:

    public class LibraryGateway : IDataGateway<Media>
    {
      public void InsertRow(Media item) { }
      public void UpdateRow(Media item) { }
      public IEnumerable<Media> GetTable() { }
    }
    

    ...我认为这应该可以满足您的需求。

    【讨论】:

      【解决方案4】:

      首先,你必须让你的界面通用:

      public interface IDataGateway<T>
      

      然后在实现时指定T

      public class LibraryGateway : IDataGateway<Media>
      

      【讨论】:

        【解决方案5】:

        您正在使用三个泛型方法定义一个非泛型接口。

        这些方法中的每一个都能够接受任何类型的T,因为T 的值在它们之间并不相同。

        您可能打算用三个非泛型方法定义一个泛型接口。

        public interface IDataGateway<T>
        {
            void InsertRow(T row);
            void UpdateRow(T row);
            IEnumerable<T> GetTable(T table);
        }
        

        【讨论】:

          【解决方案6】:

          也许像这样?

          public interface IDataGateway<T>
          {
              void InsertRow(T row);
              void UpdateRow(T row);
              IEnumerable<T> GetTable(T table);
          }
          
          public abstract class LibraryGateway<T>
          {
              public void InsertRow(T item) { }
              public void Updaterow(T item) { }
              public IEnumerable<T> GetTable<T>() { }
          }
          
          public class MediaLibraryGateway : GateWay<Media>, IDataGateway<Media>
          {
          
          }
          

          【讨论】:

            【解决方案7】:

            你错过了拼写的 Updaterow,它应该是 UpdateRow。

            实现接口的简单方法是,用鼠标点击接口名称,按ctrl+。然后选择实现接口

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多