具有通用属性的类必须是通用的?

时间:2018-04-30 02:43:04

标签: c# .net generics

我们说我有这个课程

public class Foo<T>
{
    public List<T> FooList { get; set;}
}

此类由另一个类使用,如:

public class Bar
{
    public List<Foo> Foos { get; set; }  // THIS DOESNT COMPILE
}

上述解决方案不起作用,因为它说我的泛型类型Foo需要1个类型参数。 在我的真实场景中,我认为将通用传播到Bar类是非常有意义的,例如:

public class Bar<T>
{
    public List<Foo<T>> Foos { get; set; }  // Not the solution I want
}

所以我想知道:哪个是最好的解决方案,如果有的话?我真的需要让我的Bar类通用吗?在Java中,如果我没有弄错的话,我可以做类似List<Foo<?>> Foos的事情,它会起作用......

修改

所以,正如我所说,我给出了具体的例子。 我正在为Highcharts做一些DTO课程。 Highcharts在很多其他对象中都有series个对象。这个series对象具有data属性,几乎可以是任何东西:数字列表,数字对列表等等。

所以我的通用类就是系列:

public class SeriesDto<T>
{
     public List<T> Data { get; set; }

     // Other options ...
}

它将由HighchartsDto类使用:

public class HighchartsDto {

    // Lot of things..
    // ...

    public List<SeriesDto> Series { get; set; } // doesn't compile
}

使HighchartsDto通用是没有意义的,因为相同的图表可以有不同类型的系列。

4 个答案:

答案 0 :(得分:4)

您可以添加界面:

public interface IFoo
{
}

public class Foo<T> : IFoo
{
    public List<T> FooList { get; set; }
}

public class Bar
{
    public List<IFoo> Foos { get; set; }
}

答案 1 :(得分:3)

麻烦的是你没有给出一个现实的例子,只是一个假设。

以下内容无法编译,因为它不知道您要使用哪种泛型类型?它应该猜到什么?

public class Bar
{
    public List<Foo> Foos { get; set; }  // THIS DOESNT COMPILE
}

如果您理解Bar,那么您可以做一些事情,并提前标记类型,即Bar将始终实施Foo<int>

public class Bar
{
    public List<Foo<int>> Foos { get; set; } 
}

如果您想要更多功能,并在代码中稍后选择类型,则可以执行此操作

public class Bar<T>
{
   public List<Foo<T>> Foos { get; set; } 
}

或者当 Backs 指出你可以添加一个接口时,所有这一切都在隐藏Foo<T>的成员,List<T> FooList { get; set;}在这种情况下无法使用。< / p>

你需要弄清楚你想要什么,为什么你想要它,也许更好地解释它

答案 2 :(得分:1)

Althoug我知道这个解决方案存在缺陷,这将是另一种方法。

public class Foo<T> : Foo
{
    public List<T> FooList { get; set; }
}

public class Foo
{

}

因此,您要创建一个非泛型类,您的泛型Foo派生自该类。 然后你可以这样做:

public class Bar
{
    public List<Foo> Foos { get; set; }  // THIS DOES NOW COMPILE
}

然后,如果需要,您可以将非泛型List转换为您的泛型类型列表,如下所示:

bar.Foos.Cast<Foo<GENERICTYPE>>()

但是这需要你知道它的确切类型。

答案 3 :(得分:1)

  

“这个系列对象具有几乎任何东西的数据属性:数字列表,数字对列表等等。”

对于可以是任何东西的集合来说,List<T>不是一件好事。 List<T>T类型的一个集合。也许你想要一个好的旧ArrayList,它是object的集合,因此它可以是任何东西。实质上,您必须决定内容可以具有哪种常见类型。

  1. 内容没有任何共同点,除了派生自object

    public class SeriesDto
    {
        public ArrayList Data { get; set; }
    
        // Other options ...
    }
    
    public class HighchartsDto
    {
    
        // Lot of things..
        // ...
    
        public List<SeriesDto> Series { get; set; } // doesn't compile
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var dto = new SeriesDto();
            dto.Data.Add("A string");
            dto.Data.Add(1001);
            dto.Data.Add(new TimeSpan(0, 0, 15));
    
            var list = new HighchartsDto();
            list.Series.Add(dto);
    
    
            TimeSpan time = (TimeSpan)list.Series[0].Data[2]; // 15 seconds
        }
    }
    
  2. 内容有一个共同的基本界面,其中包含与所有类型共享的所有属性和方法

    public interface ISeriesData
    {
        DateTime CreatedTime { get; }
    }
    
    public class StringData : ISeriesData
    {
        public StringData(string name)
        {
            this.Name = name;
            this.CreatedTime = DateTime.Now;
        }
        public string Name { get; }
        public DateTime CreatedTime { get; }
    }
    
    public class IntegerData : ISeriesData
    {
        public IntegerData(int value)
        {
            this.Value = value;
            this.CreatedTime = DateTime.Now;
        }
        public DateTime CreatedTime { get; }
        public int Value { get; }
    }
    
    public class SeriesDto
    {
        public List<ISeriesData> Data { get; set; }
    
        // Other options ...
    }
    
    public class HighchartsDto
    {
    
        // Lot of things..
        // ...
    
        public List<SeriesDto> Series { get; set; } // doesn't compile
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var a = new StringData("A");
            var b = new IntegerData(1001);
            var dto = new SeriesDto();
            dto.Data.Add(a);
            dto.Data.Add(b);
    
            var list = new HighchartsDto();
            list.Series.Add(dto);
    
    
            DateTime time = list.Series[0].Data[0].CreatedTime; // time
        }
    }
    
  3. 制作HighChartsDto Generic 并从中继承具体类。

    public class SeriesDto<T> 
    {
        public List<T> Data { get; set; }
        // Other options ...
    }
    
    
    public class HighChartsDto<L, T>  where L : SeriesDto<T>
    {
    
        // Lot of things..
        // ...
        public int SomethingElse { get; set; }
        public List<L> Series { get; set; } // doesn't compile
    }
    
    public class HighChartsStringDto : HighChartsDto< SeriesDto<string>, string>
    {
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var a = new SeriesDto<string>();
            a.Data.Add("A");
            a.Data.Add("B");
            a.Data.Add("C");
    
            var b = new SeriesDto<string>();
            b.Data.Add("1");
            b.Data.Add("2");
            b.Data.Add("3");
    
    
            var list = new HighChartsStringDto();
            list.Series.Add(a);
            list.Series.Add(b);
    
            string x = list.Series[1].Data[2];  // "C"
        }
    }