【问题标题】:Using dynamic type instead of none-possible generic properties使用动态类型而不是不可能的泛型属性
【发布时间】:2013-07-24 00:16:54
【问题描述】:

考虑以下代码:

    public dynamic DataGrid { get; private set; }
    public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
    {
        return DataGrid = new DataGridForm<TData, TGrid>();
    }

我正在尝试将泛型类的实例保存在 property 中以供以后使用,但如您所知:

属性、事件、构造函数等不能是通用的——只有方法 并且类型可以是通用的。大多数时候这不是问题,但我 同意有时这很痛苦 (Jon Skeet)

我想知道这是解决这种情况的好方法吗?

【问题讨论】:

  • 你不能把通用功能放在一个接口IDataGridForm中,然后让属性属于那种类型吗?
  • 我听不懂,你能详细解释一下吗?
  • 好吧,你想如何使用DataGridForm?例如,我想你想display 一个表格。因此,使用方法Display() 创建一个接口IDataGridForm。现在让您的班级DataGridForm&lt;TData, TGrid&gt; 实现该接口。它需要有Display() 方法来做到这一点。现在有一个属性public IDataGridForm DataGrid { get; private set; }。这个属性现在可以包含一个DataGridForm&lt;TData, TGrid&gt;,你可以在任何你想要的地方使用Display()
  • 感谢您的回复,看来这种方式比使用动态属性更好。
  • 有关接口的更多信息(如果需要)请参阅:MSDN

标签: c# .net generics dynamic


【解决方案1】:

正如评论中的答案所示,您可以使用基类或接口来做到这一点:

class DataGridForm {}
class DataGridForm<TData, TGrid> : DataGridForm {}

class GridConfigurator
{
    public DataGridForm DataGrid { get; private set; }
    public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
    {
        return DataGrid = new DataGridForm<TData, TGrid>();
    }
}

当添加泛型时,C# 中的大量类型和接口都以这种方式扩展。但是,我可能会重新评估您的设计,以便任何称为 GridConfig() 的东西都在缓存 DataGridForm,因为它知道类型。作为一个例子,我在我的代码中做了一个非常相似的事情:

class Vector<T> { ... }
static class Vector
{
    public static Vector<T> Create<T>(T value)
    {
        return new Vector<T>(value);
    }
}

class OtherClass
{
    public static Vector<int> MyVector = Vector.Create(1);
}

不过,您的特定用例可能不支持这种风格。

【讨论】:

  • 我意识到您解释的内容不符合我的要求,如果我必须在 DataGridForm 中有一个返回 DataGridForm&lt;TData, TGrid&gt; 的方法怎么办。在这种情况下,我也必须将基类型设为泛型。我说的对吗?
  • 如果它是一种方法则不是,但如果它是一个属性则是。在我的第二个示例中,Vector 可以毫无问题地从 Vector 继承。
  • Vector.Create的返回类型不应该是Vector吗?
  • 是的,我专门为你修好了。 :D
  • 您的属性或方法可以返回一个 DataGridForm,它是 DataGridForm 的一个实例。
【解决方案2】:

在这种情况下,您的类型本身必须是通用的。

    class GridConfigurator<TData, TGrid>
       where TData : class
    {
        public DataGridForm<TData, TGrid> DataGrid { get; private set; }
        public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>()
        {
            return DataGrid = new DataGridForm<TData, TGrid>();
        }
    }

但我不明白这门课的目的。 GridConfig 方法具有设置 DataGrid 属性(具有私有设置器)的不明显副作用。如果我使用这个类,我永远不会猜到 GridConfig() 返回给我的值也设置为 DataGrid 属性。换句话说:

var configurator = new GridConfigurator();
var firstGrid = configurator.GridConfig();
var firstReference = configurator.DataGrid;
var secondGrid = configurator.GridConfig();
var secondReference = configurator.DataGrid;

我假设以下将返回 false:

object.ReferenceEquals(firstGrid, secondGrid);

但我认为这会返回 true

object.ReferenceEquals(firstReference, secondReference);

因为在上面的代码中,我从来没有分配过 DataGrid 属性。目前尚不清楚名为 GridConfig() 的方法是否会产生这种效果。

使封闭类型(GridConfigurator)也通用似乎违背了您尝试的目的。当他们可以直接使用对 DataGridForm 的直接引用时,为什么有人会使用这种类型?

如果 GridConfig 方法应该做的不仅仅是分配一个新的 DataGridForm 的默认实例,那么让它成为一个静态工厂类,如下所示:

static class GridConfigurator
{
  public static DataGridForm<TData,TGrid> GridConfig<TData, TGrid>(...) where TData: class
  {
    var grid = new DataGridForm<TData,TGrid>();
    // do something with the parameters to this method to initialize the instance.
     return grid;
  }
}

我还会将该方法命名为 GridConfig 以外的名称。像 Configure() 或 Create()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2019-08-12
    • 2017-05-31
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多