C# 具有强类型索引的多维数组的最佳混合方法

C# 具有强类型索引的多维数组的最佳混合方法,c#,data-structures,collections,C#,Data Structures,Collections,我有一个多维数组 int[][][] MyValues; 我想要的是通过强类型等价物(如枚举)访问索引。我知道您可以从枚举类型中获取枚举值,但这对我来说有点冗长 我宁愿有一种方法来强类型索引 例如: int CarNumber = MyValues[Racetrack.Daytona][Race.Daytona500][Driver.JGordon]; 由于它类似于enum,这将防止抛出任何越界异常,而且它为所有索引提供了一个良好的人类可读的含义 我已经使用字典方法实现了这一点,但它似乎有点

我有一个多维数组

int[][][] MyValues;
我想要的是通过强类型等价物(如枚举)访问索引。我知道您可以从枚举类型中获取枚举值,但这对我来说有点冗长

我宁愿有一种方法来强类型索引

例如:

int CarNumber = MyValues[Racetrack.Daytona][Race.Daytona500][Driver.JGordon];
由于它类似于enum,这将防止抛出任何越界异常,而且它为所有索引提供了一个良好的人类可读的含义

我已经使用字典方法实现了这一点,但它似乎有点笨手笨脚:

Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>> =
    new Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>();

字典明显的问题。。
List
对您不起作用吗

枚举是否相当小,值为0…n?如果是这样,您可以使用多维数组,但要公开索引器。请注意,下面的代码使用的是矩形数组,而不是锯齿形数组,但是您可以非常轻松地对其进行调整

// In a static class somewhere. Just a convenience method to check
// whether a value is defined or not. See comment in indexer.
public static void CheckDefined<T>(this T value, String name)
    where T : struct
{
    if (!Enum.IsDefined(typeof(T), value))
    {
        throw new ArgumentOutOfRangeException(name);
    }
}


// Somewhere else...
private static int GetLength<T>() where T : struct
{
    return Enum.GetValues(typeof(T)).Length;
}

private int[,,] array = new int[GetLength<Racetrack>(), 
                                GetLength<Race>(),
                                GetLength<Driver>()];

public int this Car[Racetrack racetrack, Race race, Driver driver]
{
  get
  {
    // If you don't care about just getting an
    // IndexOutOfRangeException, you could skip these three lines.
    racetrack.CheckDefined("racetrack");
    race.CheckDefined("race");
    driver.CheckDefined("driver");
    return array[(int) racetrack, (int) race, (int) driver);
  }
}
//在某个静态类中。只是一种方便的检查方法
//是否定义了值。请参阅索引器中的注释。
公共静态void CheckDefined(此T值,字符串名称)
其中T:struct
{
如果(!Enum.IsDefined(typeof(T),value))
{
抛出新ArgumentOutOfRangeException(名称);
}
}
//在别的地方。。。
私有静态int GetLength(),其中T:struct
{
返回Enum.GetValues(typeof(T)).Length;
}
私有整数[,]数组=新整数[GetLength(),
GetLength(),
GetLength()];
这辆车的公共部分[赛道,赛道,赛车,驾驶员]
{
得到
{
//如果你不在乎得到一个
//除此之外,您可以跳过这三行。
赛马场。勾选定义(“赛马场”);
种族。已定义(“种族”);
驱动程序。检查定义(“驱动程序”);
返回阵列[(内部)赛道,(内部)比赛,(内部)驾驶员);
}
}

字典中使用三元组
作为键(定义您自己的类)如何


如果你真的需要使用数组,我认为你最好还是将它包装在一个自定义类中,该类只允许使用
Racetrack
Race
Driver
枚举进行访问。

我觉得你应该使用数组而不是数组。假设以下枚举(基于公式1!):

基本结构如下:

public class Race
{
    int Year { get; set; }
    Track Track { get; set; }
    Driver[] Placings { get; set; }
    public int this[Driver driver] { } // placing by driver
}

public class Results
{
    YearResults this[int index] { }
    DriverResults this[Driver index] { }
    TrackResults this[Track index] { }
    ConstructorResults this[Constructor index] { }
}

public class YearResults
{
    YearDriverResults this[Driver index] { }
}
这当然是一个部分实现,但您可以通过这种方式使用索引器做一些非常酷的事情。例如,您可以使用任何顺序的值组合访问您的信息(假设您设置了所有中间类)


它比多维数组或元组键词典更冗长,但我认为它会为您提供更优雅的代码。

我不认为字典方法不好,但它并不优雅。如果您为字典创建别名,情况会更好:

using RaceSetup = Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>;

使用RaceSetup=DictionaryList不允许您在不强制转换或编写大量访问器的情况下将枚举用作索引器来获取实际值,并且不是类型安全的。所以不是。我认为列表是类型安全的?我想我很困惑。它是安全的,因为它的值,而不是索引器。这是一个很好的观点。有时我们会陷入思考问题就像锤子一样,我们忘记了它可能不是钉子。可能是螺丝钉或胶水。嗯,不,我不需要有各种属性或方法的赛车道或赛车对象。它只是一组带约束的数字。但就像我说的,我真的没有想过要将它们定义为自己的类。你能解释一下“public int this Car”是关于什么的?这是为了什么?它声明了一个索引器。看到字典方法的更大问题是它创建了混乱的初始化代码。这不是一个大问题,但仍然很难看。
using RaceSetup = Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>;
class RaceSetup : Dictionary<Racetrack,Dictionary<Race,<Dictionary<Driver,int>>>
{}