C#数组还是字典?

我想知道C#数组是否具有恒定的访问速度?
我需要在静态数组中存储1000个项目,这些项目将在服务器启动期间初始化。 此数组将以只读方式使用,因此不会对数组进行任何更改。
我应该使用简单的C#数组(新的MyClass [])或字典。

我是C#的新手,并试图了解C#数组访问是如何工作的。
它们可以通过速度与c ++数组进行比较吗?

最佳选择取决于您需要如何访问元素。

如果要通过索引访问它们,请使用数组。 C#中的数组具有恒定的访问速度,就访问速度而言,与C ++数组非常相似。

但是,字典具有非常快的访问权限( Item属性 接近 O(1)访问时间,但取决于存储的密钥对GetHashCode的实现有多好)。 如果您需要根据键值而不是索引来查找项目,那么字典将是合适的。

是的,如果你知道索引速度是常数O(1),就像在哈希表支持的字典中查找(例如Dictionary <>)。

如果索引未知,则必须执行搜索(如果项目未排序为O(n)则为线性,如果为O(log n),则为二进制)。

也就是说,实际上数组查找会更快,因为哈希表查找是两个操作:计算键的哈希值以获取索引并从该索引处的内部数组中检索值。

还要注意,如果密钥的哈希码被严重实现,哈希表的神奇属性很快就会消失,在最坏的情况下(每个密钥都有相同的哈希码),你最终会得到一个精心设计的链表,每个查找将以O(n)为代价进行线性搜索。 仔细检查那些哈希码!

这取决于您从arrays中获取元素的方式。 如果要按数组中的位置(索引)获取元素,那么数组将更快(或者至少不比字典慢)。 如果要搜索数组中的元素,那么字典会更快。

最后一篇文章的更新……代码现在包括列表数据结构的类。 我从代码中删除了一些错误。 它现在应该提供正确的结果。

似乎对于一维数据结构,列表结构实际上可以比数组更快。 但对于二维结构,如下面的代码所示,数组比列表快得多,并且明显快于字典。

但这一切都取决于你想要使用的数据结构。 对于相对较小的数据集,字典和列表通常是更方便使用的结构。

public interface IDataStructureTimeTestHandler { void PerformTimeTestsForDataStructures(); } public class DataStructureTimeTestHandler : IDataStructureTimeTestHandler { // Example of use: //IDataStructureTimeTestHandler iDataStructureTimeTestHandler = new DataStructureTimeTestHandler(); //iDataStructureTimeTestHandler.PerformTimeTestsForDataStructures(); private IDataStructureTimeTest[] iDataStructureTimeTests; private TimeSpan[,] testsResults; public DataStructureTimeTestHandler() { iDataStructureTimeTests = new IDataStructureTimeTest[3]; testsResults = new TimeSpan[4, 3]; } public void PerformTimeTestsForDataStructures() { iDataStructureTimeTests[0] = new ArrayTimeTest(); iDataStructureTimeTests[1] = new DictionaryTimeTest(); iDataStructureTimeTests[2] = new ListTimeTest(); for (int i = 0; i < iDataStructureTimeTests.Count(); i++) { testsResults[0, i] = iDataStructureTimeTests[i].InstantiationTime(); testsResults[1, i] = iDataStructureTimeTests[i].WriteTime(); testsResults[2, i] = iDataStructureTimeTests[i].ReadTime(LoopType.For); testsResults[3, i] = iDataStructureTimeTests[i].ReadTime(LoopType.Foreach); } } } public enum LoopType { For, Foreach } public interface IDataStructureTimeTest { TimeSpan InstantiationTime(); TimeSpan WriteTime(); TimeSpan ReadTime(LoopType loopType); } public abstract class DataStructureTimeTest { protected IStopwatchType iStopwatchType; protected long numberOfElements; protected int number; protected delegate void TimeTestDelegate(); protected DataStructureTimeTest() { iStopwatchType = new StopwatchType(); numberOfElements = 10000000; } protected void TimeTestDelegateMethod(TimeTestDelegate timeTestMethod) { iStopwatchType.StartTimeTest(); timeTestMethod(); iStopwatchType.EndTimeTest(); } } public class ArrayTimeTest : DataStructureTimeTest, IDataStructureTimeTest { private int[,] integerArray; public TimeSpan InstantiationTime() { TimeTestDelegateMethod(new TimeTestDelegate(InstantiationTime_)); return iStopwatchType.TimeElapsed; } private void InstantiationTime_() { integerArray = new int[numberOfElements, 2]; } public TimeSpan WriteTime() { TimeTestDelegateMethod(new TimeTestDelegate(WriteTime_)); return iStopwatchType.TimeElapsed; } private void WriteTime_() { number = 0; for (int i = 0; i < numberOfElements; i++) { integerArray[i, 0] = number; integerArray[i, 1] = number; number++; } } public TimeSpan ReadTime(LoopType dataStructureLoopType) { switch (dataStructureLoopType) { case LoopType.For: ReadTimeFor(); break; case LoopType.Foreach: ReadTimeForEach(); break; } return iStopwatchType.TimeElapsed; } private void ReadTimeFor() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeFor_)); } private void ReadTimeFor_() { for (int i = 0; i < numberOfElements; i++) { number = integerArray[i, 1]; } } private void ReadTimeForEach() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeForEach_)); } private void ReadTimeForEach_() { foreach (int i in integerArray) { number = i; } } } public class DictionaryTimeTest : DataStructureTimeTest, IDataStructureTimeTest { private Dictionary integerDictionary; public TimeSpan InstantiationTime() { TimeTestDelegateMethod(new TimeTestDelegate(InstantiationTime_)); return iStopwatchType.TimeElapsed; } private void InstantiationTime_() { integerDictionary = new Dictionary(); } public TimeSpan WriteTime() { TimeTestDelegateMethod(new TimeTestDelegate(WriteTime_)); return iStopwatchType.TimeElapsed; } private void WriteTime_() { number = 0; for (int i = 0; i < numberOfElements; i++) { integerDictionary.Add(number, number); number++; } } public TimeSpan ReadTime(LoopType dataStructureLoopType) { switch (dataStructureLoopType) { case LoopType.For: ReadTimeFor(); break; case LoopType.Foreach: ReadTimeForEach(); break; } return iStopwatchType.TimeElapsed; } private void ReadTimeFor() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeFor_)); } private void ReadTimeFor_() { for (int i = 0; i < numberOfElements; i++) { number = integerDictionary[i]; } } private void ReadTimeForEach() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeForEach_)); } private void ReadTimeForEach_() { foreach (KeyValuePair i in integerDictionary) { number = i.Key; number = i.Value; } } } public class ListTimeTest : DataStructureTimeTest, IDataStructureTimeTest { private List integerList; public TimeSpan InstantiationTime() { TimeTestDelegateMethod(new TimeTestDelegate(InstantiationTime_)); return iStopwatchType.TimeElapsed; } private void InstantiationTime_() { integerList = new List(); } public TimeSpan WriteTime() { TimeTestDelegateMethod(new TimeTestDelegate(WriteTime_)); return iStopwatchType.TimeElapsed; } private void WriteTime_() { number = 0; for (int i = 0; i < numberOfElements; i++) { integerList.Add(new int[2] { number, number }); number++; } } public TimeSpan ReadTime(LoopType dataStructureLoopType) { switch (dataStructureLoopType) { case LoopType.For: ReadTimeFor(); break; case LoopType.Foreach: ReadTimeForEach(); break; } return iStopwatchType.TimeElapsed; } private void ReadTimeFor() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeFor_)); } private void ReadTimeFor_() { for (int i = 0; i < numberOfElements; i++) { number = integerList[i].ElementAt(1); } } private void ReadTimeForEach() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeForEach_)); } private void ReadTimeForEach_() { foreach (int[] i in integerList) { number = i.ElementAt(1); } } } 

C#中的数组访问是一个简单的索引操作,而字典是一个哈希表查找。 除了语言执行的边界检查的一些小开销之外,数组与C ++数组相当。

如果您不打算更改内容,我会使用数组来表示数据大小,如果没有别的话。

这是我刚刚写的东西。 对于不同的数据结构,它可以相当容易地扩展。 它包括每个数据结构的类(当前只是数组和字典)。

客户端代码只有两行:

IDataStructureTimeTestHandler iDataStructureTimeTestHandler = new DataStructureTimeTestHandler(); iDataStructureTimeTestHandler.PerformTimeTestsForDataStructures();

其余代码是:

 public interface IStopwatchType { TimeSpan TimeElapsed { get; } void StartTimeTest(); void EndTimeTest(); } public class StopwatchType : TailoredType, IStopwatchType { private Stopwatch stopwatch; private TimeSpan timeElapsed; public TimeSpan TimeElapsed { get { return timeElapsed; } } public StopwatchType() { } public void StartTimeTest() { ClearGarbage(); stopwatch = Stopwatch.StartNew(); } public void EndTimeTest() { stopwatch.Stop(); timeElapsed = stopwatch.Elapsed; } private void ClearGarbage() { GC.Collect(); GC.WaitForPendingFinalizers(); } } public interface IDataStructureTimeTestHandler { void PerformTimeTestsForDataStructures(); } public class DataStructureTimeTestHandler : IDataStructureTimeTestHandler { private IDataStructureTimeTest[] iDataStructureTimeTests; private TimeSpan[,] testsResults; public DataStructureTimeTestHandler() { iDataStructureTimeTests = new IDataStructureTimeTest[2]; testsResults = new TimeSpan[4, 2]; } public void PerformTimeTestsForDataStructures() { iDataStructureTimeTests[0] = new ArrayTimeTest(); iDataStructureTimeTests[1] = new DictionaryTimeTest(); for (int i = 0; i < iDataStructureTimeTests.Count(); i++) { testsResults[0, i] = iDataStructureTimeTests[0].InstantiationTime(); testsResults[1, i] = iDataStructureTimeTests[0].WriteTime(); testsResults[2, i] = iDataStructureTimeTests[0].ReadTime(LoopType.For); testsResults[3, i] = iDataStructureTimeTests[0].ReadTime(LoopType.Foreach); } } } public enum LoopType { For, Foreach } public interface IDataStructureTimeTest { TimeSpan InstantiationTime(); TimeSpan WriteTime(); TimeSpan ReadTime(LoopType loopType); } protected abstract class DataStructureTimeTest { protected IStopwatchType iStopwatchType; protected long numberOfElements; protected int number; protected delegate void TimeTestDelegate(); protected DataStructureTimeTest() { iStopwatchType = new StopwatchType(); numberOfElements = 100000; } protected void TimeTestDelegateMethod(TimeTestDelegate timeTestMethod) { iStopwatchType.StartTimeTest(); timeTestMethod(); iStopwatchType.EndTimeTest(); } } public class ArrayTimeTest : DataStructureTimeTest, IDataStructureTimeTest { private int[] integerArray; public TimeSpan InstantiationTime() { TimeTestDelegateMethod(new TimeTestDelegate(InstantiationTime_)); return iStopwatchType.TimeElapsed; } private void InstantiationTime_() { integerArray = new int[numberOfElements]; } public TimeSpan WriteTime() { TimeTestDelegateMethod(new TimeTestDelegate(WriteTime_)); return iStopwatchType.TimeElapsed; } private void WriteTime_() { number = 0; for (int i = 0; i < numberOfElements; i++) { integerArray[i] = number; number++; } } public TimeSpan ReadTime(LoopType dataStructureLoopType) { switch (dataStructureLoopType) { case LoopType.For: ReadTimeFor(); break; case LoopType.Foreach: ReadTimeForEach(); break; } return iStopwatchType.TimeElapsed; } private void ReadTimeFor() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeFor_)); } private void ReadTimeFor_() { for (int i = 0; i < numberOfElements; i++) { number = integerArray[i]; } } private void ReadTimeForEach() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeForEach_)); } private void ReadTimeForEach_() { foreach (int i in integerArray) { number = i; } } } public class DictionaryTimeTest : DataStructureTimeTest, IDataStructureTimeTest { private Dictionary integerDictionary; public TimeSpan InstantiationTime() { TimeTestDelegateMethod(new TimeTestDelegate(InstantiationTime_)); return iStopwatchType.TimeElapsed; } private void InstantiationTime_() { integerDictionary = new Dictionary(); } public TimeSpan WriteTime() { TimeTestDelegateMethod(new TimeTestDelegate(WriteTime_)); return iStopwatchType.TimeElapsed; } private void WriteTime_() { number = 0; for (int i = 0; i < numberOfElements; i++) { integerDictionary.Add(number, number); number++; } } public TimeSpan ReadTime(LoopType dataStructureLoopType) { switch (dataStructureLoopType) { case LoopType.For: ReadTimeFor(); break; case LoopType.Foreach: ReadTimeForEach(); break; } return iStopwatchType.TimeElapsed; } private void ReadTimeFor() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeFor_)); } private void ReadTimeFor_() { for (int i = 0; i < numberOfElements; i++) { number = integerDictionary[i]; } } private void ReadTimeForEach() { TimeTestDelegateMethod(new TimeTestDelegate(ReadTimeForEach_)); } private void ReadTimeForEach_() { foreach (KeyValuePair i in integerDictionary) { number = i.Value; } } }