C# 泛型集合

标签 c# generics

我是从 Java 背景转到 C# 的,并且不断遇到类似的泛型问题,而这些问题在 Java 中很容易解决。

给定类:

interface IUntypedField { }
class Field<TValue> : IUntypedField { }

interface IFieldMap
{
    void Put<TValue>(Field<TValue> field, TValue value);
    TValue Get<TValue>(Field<TValue> field);
}

我想写这样的东西:

class MapCopier
{
    void Copy(IEnumerable<IUntypedField> fields, IFieldMap from, IFieldMap to)
    {
        foreach (var field in fields)
            Copy(field, from, to); // <-- clearly doesn't compile as field is IUntypedField not Field 
    }

    void Copy<TValue>(Field<TValue> field, IFieldMap from, IFieldMap to)
    {
        to.Put(field, from.Get(field));
    }
}

在 Java 中,这很容易解决,因为字段集合是一个 Iterable<Field<?>>。你可以调用Copy(Field, IFieldMap, IFieldMap)直接。

在 C# 中,我发现自己对 TValue 的所有可能值进行切换/转换(这闻起来很可怕,必须为您添加的每种类型添加一个 case 显然是一个等待发生的错误,并且只有在类型集是有限的情况下才可行):

foreach (var field in fields)
{
    switch (field.Type) // added an enum to track the type of Field's parameterised type
    {
    case Type.Int:   Copy((Field<int>)field, from, to); break;
    case Type.Long:  Copy((Field<long>)field, from, to); break; 
    ...
    }
}

我有时做的另一个选择是将功能移到 Field 类中,这又很糟糕。这不是该领域的责任。至少这避免了巨大的转变:

interface IUntypedField { void Copy(IFieldMap from, IFieldMap to); }
class Field<TValue> : IUntypedField 
{ 
    void Copy(IFieldMap from, IFieldMap to)
    {
        to.Put(this, from.Get(this));
    }
}

...

    foreach (var field in fields)
        field.Copy(from, to);

如果您可以编写多态扩展方法(即上面 IUntypedField 和 Field 中的 Copy 方法),那么您至少可以将代码放在负责它的类旁边。

我是否遗漏了 C# 的一些功能,使这成为可能。或者是否有一些可以使用的功能模式?有什么想法吗?

(最后一件事,我目前停留在 .Net 3.5 上,所以不能使用任何协变/逆变,但仍然有兴趣知道他们在这里有什么帮助,如果有的话)。

最佳答案

您至少可以使用反射来避免 switch { }。 fw 4.0 的协变/逆变在这种情况下无济于事。也许可以从使用 dynamic 关键字中获益。

// untested, just demonstates concept
class MapCopier
{
    private static void GenericCopy<TValue>(Field<TValue> field, IFieldMap from, IFieldMap to)
    {
        to.Put(field, from.Get(field));
    }

    public void Copy(IEnumerable<IUntypedField> fields, IFieldMap from, IFieldMap to)
    {
        var genericMethod = typeof(MapCopier).GetMethod("GenericCopy");
        foreach(var field in fields)
        {
            var type = field.GetType().GetGenericArguments()[0];
            var method = genericMethod.MakeGenericMethod(type);
            method.Invoke(null, new object[] { field, from, to });
        }
    }
}

关于C# 泛型集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4581965/

相关文章:

c - 通用排序适用于整数但不适用于其他类型

generics - Rust 中 trait 的冲突实现

java - 创建泛型类型的数组

swift - 使用泛型在 Swift 中实现类似 registerClass 的行为

c# - 沿 Windows 应用程序部署 Postgresql

c# - 以编程方式安排/创建 Skype for Business session

c# - 将 Outlook 电子邮件的所有附件转换为 PDF

c# - 如何建立这种 EF 关系?

c# - 在 .NET 中创建加密安全随机 GUID

java - 为什么我不能在这段代码中使用 Collections.max() 函数? - java