C#泛型列表

3

我有一个类,它映射到数据库中的一个字段。该类只关心字段的名称及其相关的.NET类型。该类型可以是字符串、整数、日期时间等。

class Foo()
{
    string Name { get; set; }
    Type FooType { get; set; }
}

我有另一个继承自Foo的类,增加了一个值属性。目前,我将该值存储为对象,并使用switch语句根据基类FooType对值进行装箱。

class FooWithStuff() : Foo
{
    object Value { get; set; }   
}

有没有办法使用泛型来实现对值类型的类型安全?

编辑:我已经将关键要求加粗。当声明一个名为Foo的列表时,它需要一个类型。如果我针对自定义类执行此操作,我会创建一个接口并使用它。但是在这里我使用int、string、DateTime等。Int是一个结构体,string是一个对象,因此Foo< object>不能同时适用于两者。

6个回答

9
class Foo
{
    public string Name { get; set; }
    public Type Type { get; set; }
}

class Bar<T> : Foo
{
    public T Value { get; set; }

    public Bar()
    {
        base.Type = typeof( T );
    }
}

8

请按照以下方式定义您的类:

class Foo<T> : IFoo
{

    public Foo(string name)
    {
        Name = name;
    }

    string Name { get; set; }
    T Value {get; set;}
    Type FooType { get { return typeof(T); } }
}

您可以将接口IFoo定义为:
string Name { get; set; }
Type FooType { get; set; }

声明一个列表:

List<IFoo> list = new List<IFoo>();

这似乎是最完整、准确和最干净的实现。我目前正在尝试它。 - blu

2
如果您想为Foo添加价值并使其成为通用的,可以执行以下操作...
class Foo<T>
{
    T Value {get; set;}
}

Foo<int> myFoo = new Foo<int>();
myFoo.Value = 7;

但这样做并不能满足T与FooType相同的附加约束? - Dirk Vollmar
你将不再存储FooType:取而代之的是你可以调用Foo<T>.GetType().GetGenericArguments[0]。 - Joel Coehoorn
或者创建一个返回该类型的属性: public Type FooType { get { return typeof(T); } } - configurator
我想这就是我想要的,如果你已经有了类型,我觉得没有必要使用FooType。如果你仍然想转换为基类,你可以实现一个Foo接口,我会发一个例子。 - Quintin Robinson

1

在这种情况下,我会使用接口而不是通用类继承。

编辑:澄清一下。我会为Foo使用接口,为FooWithStuff使用通用类:

public interface IFoo
{
  string Name{get;set;}
  Type FooType{get;set;}
}

public class FooWithStuff<T>:IFoo
{
   T Value {get;set;}
}

为什么你要在接口上保留类型,它对于转换并不需要? - blu
我想我没有理解重点。@divo,是的,我在那方面有些过于假设了。 - Mike_G

0

是的,实际上你可以放弃继承,只需……

public class Foo<T>
{
  public string Name {get;set;}
  public T Value {get;set;}
  public Type FooType
  {
     get
     {
       return typeof(T);
     }
  }
}

此外,使用 linq 你可以直接从列表中提取所需的类型,因此如果你只对字符串字段感兴趣,你可以...

List<object> list = getAllmyFoos();
foreach(Foo<string> sfoo in list.OfType<Foo<string>>())
{
  ...blah
}

编辑:添加了FooType。


问题在于当我声明列表时需要指定类型,而它存储的是整数、字符串、日期时间等。 - blu
当然,如果你需要它的话,你就需要它。 - Tim Jarvis

-2
我建议使用2个接口:
public interface IFoo
{
  string Name {get; }
  Type Type { get; }
  object Value {get; set;}
}

public interface IFoo<T> : IFoo
{
  T Value {get; set}
}

然后实现它:

public class Foo<T> : IFoo<T>
{
   private T value;
   public Foo(string name, T value)
   {
     this.name = name;
     this.value = value;
   }

   public string Name { get { return name; } }
   public Type Type { get { return typeof(T); } }
   public T Value
   {
      get { return value; }
      set { value = value; }
   }

   object IFoo.Value
   {
      get { return value; }
      set { value = (T)value; }  // can check type before
   }
}

这样,您也可以在非泛型上下文中轻松使用IFoo接口。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接