通用类型的HashSet

时间:2016-12-07 19:04:28

标签: c# .net generics hashset

我已经找到了有关此主题的一些信息,但这些都是关于典型的类 - 我不知道如何将下面的类转换为通用版本。

我继承了现有的代码,该代码使用SqlHashSet类为数据库的参数设置整数值。它看起来像这样:

namespace Services
{
    public class SqlHashSet : HashSet<int>, IEnumerable<SqlDataRecord>
    {
        SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", SqlDbType.Int));       
        foreach (var data in this)
        {
            ret.SetValue(0, data);
            yield return ret;
        }
    }
}

由于代码的结构,我必须使用SqlHashSet。我的问题是我需要一个字符串的SqlHashSet。

我想也许我可以在类声明中使用HashSet<T>但是我还必须检查值是否为SqlDbType.int或SqlDbType.VarChar

所以,我的问题是:

  1. 我可以这样做吗?

  2. 使用<T>需要做什么?

  3. 也许没有第三个问题;也许那时我可以逐步完成代码,一旦我使用泛型类型,并弄清楚如何确定SqlDbType来设置值。

2 个答案:

答案 0 :(得分:1)

(请注意,您发布的代码不会编译;您不能直接在类中编写语句,它们必须在方法中)

您无法创建真正的通用类,因为您需要使用不同的SqlDbType,具体取决于T的类型。但如果你不介意做一些有点丑陋的事情,你可以这样做:

public class SqlHashSet<T> : HashSet<T>, IEnumerable<SqlDataRecord>
{
    private static readonly SqlDbType _sqlDbType = GetSqlDbType();
    private static SqlDbType GetSqlDbType()
    {
        if (typeof(T) == typeof(int))
            return SqlDbType.Int;
        if (typeof(T) == typeof(string))
            return SqlDbType.String;

        ...

        throw new InvalidOperationException($"Can't find the SqlDbType for {typeof(T)}");
    }

    ...

    SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", _sqlDbType));
}

Lee的回答中提出的方法类似但更清晰,如果您不介意必须为每种值类型创建单独的类。

答案 1 :(得分:1)

您可以添加基类:

public abstract class SqlHashSetBase<T> : HashSet<T>, IEnumerable<SqlDataRecord>
{
    protected abstract SqlDbType DbType { get; }

    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
    {
        SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", this.DbType));
        foreach (T data in this)
        {
            ret.SetValue(0, data);
            yield return ret;
        }
    }
}

然后更改现有的课程:

public class SqlHashSet : SqlHashSetBase<int> {
    protected override SqlDbType DbType {
        get { return SqlDbType.Int; }
    }
}

并添加一个新的:

public class SqlStringHashSet : SqlHashSetBase<string> {
    protected override SqlDbType DbType {
        get { return SqlDbType.NVarChar; }
    }
}

您可能需要考虑将T => SqlDbType映射提取到自己的类中,并将其作为参数传递,而不是使用抽象方法。您可能还想考虑使用合成而不是直接从HashSet<T>继承。