我已经找到了有关此主题的一些信息,但这些都是关于典型的类 - 我不知道如何将下面的类转换为通用版本。
我继承了现有的代码,该代码使用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
所以,我的问题是:
我可以这样做吗?
使用<T>
需要做什么?
也许没有第三个问题;也许那时我可以逐步完成代码,一旦我使用泛型类型,并弄清楚如何确定SqlDbType来设置值。
答案 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>
继承。