我们说我有这个课程
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
通用是没有意义的,因为相同的图表可以有不同类型的系列。
答案 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
的集合,因此它可以是任何东西。实质上,您必须决定内容可以具有哪种常见类型。
内容没有任何共同点,除了派生自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
}
}
内容有一个共同的基本界面,其中包含与所有类型共享的所有属性和方法
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
}
}
制作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"
}
}