【发布时间】:2014-05-22 06:40:45
【问题描述】:
我有一些应该生成图表的类。我有三个类为图表系列使用不同类型的数据。我将只提供这些类的属性,以避免混淆:)
public class PointBase
{
public decimal X { get; set; }
}
public class Point : PointBase
{
public decimal Y { get; set; }
}
public class Bubble : Point
{
public decimal Size { get; set; }
}
这三个类被用作图表系列中的基本数据。图表系列在其他三个类(图表类)中表示为 Dictionary 对象。为了专注于具体问题,我不会提供图表类的代码。我将只提供类的名称:
- CoordinateChart(使用 PointBase 作为基本数据)。
- 散点图(使用点)。
- BubbleChart(使用 Bubble)。
我有以下方法对我的所有图表类执行完全相同的算法。这就是为什么我决定使用泛型来制作该方法。
public Dictionary<string, T[]> GenerateSeriesDataDictionary<T>(string[] series, string[] categories) where T : PointBase, new()
{
// Create a new Dictionary.
Dictionary<string, T[]> seriesData = new Dictionary<string, T[]>();
// Gets the number of categories and assigns the categoriesNumber variable with the returned value.
int categoriesNumber = categories.Length;
foreach (string serie in series)
{
Dictionary<string, T> categoriesData = (Dictionary<string, T>)GetCategoriesData(serie);
// Create a new array of Ts that will store the data for the current serie.
T[] dataArray = new T[categories.Length];
for (int i = 0; i < categoriesNumber; i++)
{
// If the serie contains a value for the current category, store it in the array.
// Otherwise, set the value of the current element of the array to the default one.
dataArray[i] = categoriesData.ContainsKey(categories[i]) ? categoriesData[categories[i]] : new T();
}
// Add the dataArray to the seriesData Dictionary.
seriesData.Add(serie, dataArray);
}
return seriesData;
}
所以,上面的方法接收到两个字符串数组。第一个代表系列的名称,例如“东京”和“伦敦”。第二个代表图表的类别名称——例如月份的名称——“一月”、“二月”等。
这个方法应该创建一个 Dictionary 对象,它使用一个系列的名称作为键和一个相应的对象数组,代表每个类别的数据(在我的例子中 - 每个月)。例如,字典中的单个键值对应如下所示: 关键字:“伦敦”;值:17、16、20、25(假设数据代表每个月的最高温度)。
每当我创建折线图、散点图或气泡图(由 CoordinateChart、ScatterChart 和 BubbleChart 类表示)时,我基本上都在执行相同的算法。唯一不同的是我正在生成的字典的类型。
- CoordinateChart 使用 Dictionary(string, PointBase[])
- ScatterChart 使用 Dicitonary(string, Point[])
- BubbleChart 使用 Dictionary(string, Bubble[])
我将 '' 字符替换为 '(' 和 ')',因为它们似乎消失了 :)
这就是为什么我决定将应该生成 Dictionary 对象的逻辑放在一个单独的方法中,然后在每个类中覆盖这个方法。
我的方法是这样的:
public virtual Dictionary<string, PointBase> GetCategoriesData(string serie)
{
Dictionary<string, PointBase> categoriesData = sqlResultDataTable.AsEnumerable()
.Where(row => row["City"].ToString() == serie)
.Select(row => new KeyValuePair<string, PointBase>(row["Month"].ToString(), new PointBase(decimal.Parse(row["Temperature"].ToString()))))
.ToDictionary(item => item.Key, item => item.Value);
return categoriesData;
}
此方法基本上获取表示系列(例如,“伦敦”)的“月份”和“温度”值的所有键值对。
所以,我这样做是为了实现代码的可重用性。否则,我可以在我的所有三个类中执行相同的操作,并且可以在每个类中提供 GenerateSeriesDataDictionary 方法的单独实现,但我认为这不是一个好方法。
一切正常,但我在这一行得到一个错误:
Dictionary<string, T> categoriesData = (Dictionary<string, T>)GetCategoriesData(serie);
错误消息指出:'Cannot convert type Dictionary(string, PointBase) to Dictionary(string, T)'。
我将 '' 字符替换为 '(' 和 ')',因为它们似乎消失了 :)
我能做什么?
【问题讨论】:
-
为什么不能在需要使用集合的时候循环遍历 categoriesData 字典并使用
.Value is Point或.Value is Bubble匹配值?
标签: c# generics inheritance polymorphism code-reuse