2010-03-08 4 views
3

Возможно ли, чтобы две строки имели разные хэши? У меня есть Hashtable, среди прочего ключевой «путь». Когда я перебираю элементы в таблице для ее печати, я вижу, что ключ существует..NET Hashtable - «Тот же» ключ, разные хэши

При попытке найти его, однако, нет соответствующего элемента. Отладка предполагает, что строка, которую я ищу, имеет другой хэш, чем тот, который я поставляю в качестве ключа.

Этот код находится в проекте Monorail Castle, используя Brail как механизм просмотра. Ключ я ищу вставляется в Brail линии, как это:

UrlHelper.Link(node.CurrentPage.LinkText, {@params: {@path: "/Page1"}}) 

Затем в этом методе (в пользовательском IRoutingRule):

public string CreateUrl(System.Collections.IDictionary parameters) 
{ 
    PrintDictionaryToLog(parameters); 
    string url; 
    if (parameters.Contains("path")) { 
     url = (string)parameters["path"]; 
    } 
    else { 
     return null; 
    } 
} 

ключ напечатан в журнале, но функция возвращает null. Я не знал, что это может быть даже проблемой с .net-строками, но я предполагаю, что это какая-то проблема с кодировкой?

О, и это работает моно.

По желанию, здесь соответствующая строка из журнала:

2010-03-08 22:58:00,504 [7] DEBUG Knickle.Framework.Routing.PageRoute (null) - Parameters: {System.String controller=null, System.String path=Page1, System.String path=/Page1, System.String action=null, System.String area=null} 

Кроме того, здесь я добавил строку кода выше печатного журнала вызова:

parameters.Add("path", "Page1"); 

Взгляните в журнале, и вы заметите, что есть два ключа пути. Отладчик показывает обе клавиши в разных местах таблицы.

ответ

1

Никогда не должно было случиться. Проверьте наличие пробелов, экранирование URL и т. Д.

1

Строки, которые равны StringComparison.Ordinal, или просто String.Equals, будут иметь одинаковый хэш-код при любых обстоятельствах.

2

Вот ссылка на MSDN на GetHashCode for Strings. Если они равны, хэш-коды должны совпадать, но если они не равны, они все равно могут иметь один и тот же хеш (как бы мала эта возможность).

http://msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx

Из статьи:

Если две строковые объекты равны, метод GetHashCode возвращает одинаковые значения. Однако для каждой уникальной строки не существует уникального значения хэш-кода . Различные строки могут возвращать тот же хэш-код.

0

В какой версии Mono вы использовали? Это может быть ошибка в Mono, если это так, что сообщение об ошибке будет приветствоваться.

Но да, я согласен с Seva, что, вероятно, причиной являются некоторые конечные пробелы или разделители или какая-то другая проблема с кодировкой, из-за чего строки отличаются каким-то тонким способом и приводят к различным хэшам.

1

Это эта строка, которая делает это [Castle.MonoRail.Framework.Services.DefaultUrlBuilder: 397] ...

// Forces copying entries to a non readonly dictionary, preserving the original one 
parameters = new Hashtable(parameters, StringComparer.InvariantCultureIgnoreCase); 

Если IEqualityComparer удален, проблема исчезнет.

Если это моно ошибка (которая, как мне кажется, она должна быть), это все равно проблема с mono 2.10.8.1 (Debian 2.10.8.1-5ubuntu1).

Для проверки необходимо написать письмо и подать заявку.

+0

Эй, никогда не замечал этого ответа. Я больше не помню, в каком проекте появилась эта проблема. Поскольку это был игрушечный проект, с которого я перешел, но я никогда не решал проблему. Приятно рыть, тем не менее. –

-1

Hashtable оптимизирует поиск. Он вычисляет хэш каждого добавляемого ключа. Затем он использует этот хэш-код для быстрого поиска элемента. Это более старый тип .NET Framework. Он медленнее, чем общий тип словаря.

словарь Пример

Во-первых, вы можете создать новый Hashtable с простейшего конструктора. Когда он создается, Hashtable не имеет значений. Мы напрямую присваиваем значения индектеру, который использует квадратные скобки [].

Следующий: В примере добавляется три целых ключа с одним строковым значением для объекта Hashtable.

Добавление записей в Hashtable и отображать их [C#]

using System; 
using System.Collections; 

class Program 
{ 
    static void Main() 
    { 
    Hashtable hashtable = new Hashtable(); 
    hashtable[1] = "One"; 
    hashtable[2] = "Two"; 
    hashtable[13] = "Thirteen"; 

    foreach (DictionaryEntry entry in hashtable) 
    { 
     Console.WriteLine("{0}, {1}", entry.Key, entry.Value); 
    } 
    } 
} 

Результат

13, Thirteen 
2, Two 
1, One 

Программа отображает все объекты DictionaryEntry вернулись из счетчику в цикле Еогеасп. Вызов WriteLine содержит строку формата, которая отображает пары ключ/значение с запятой.

Foreach

Вы можете перебрать HashTables с использованием типа DictionaryEntry в Еогеасп петле. Вы также можете получить коллекцию ключей и скопировать ее в ArrayList. A DictionaryEntry содержит два объекта: ключ и значение.

Foreach DictionaryEntry Содержит Далее мы видим некоторые из наиболее распространенных и важных методов экземпляра на Hashtable. Вы хотите вызвать ContainsKey на своем Hashtable с содержимым ключа. Этот метод возвращает true, если ключ найден независимо от значения.

Также: Содержит работы таким же образом. Мы видим пример использования индексатора с квадратными скобками [].

Программа, которая использует метод Содержит [C#]

using System; 
using System.Collections; 

class Program 
{ 
    static Hashtable GetHashtable() 
    { 
    // Create and return new Hashtable. 
    Hashtable hashtable = new Hashtable(); 
    hashtable.Add("Area", 1000); 
    hashtable.Add("Perimeter", 55); 
    hashtable.Add("Mortgage", 540); 
    return hashtable; 
    } 

    static void Main() 
    { 
    Hashtable hashtable = GetHashtable(); 

    // See if the Hashtable contains this key. 
    Console.WriteLine(hashtable.ContainsKey("Perimeter")); 

    // Test the Contains method. It works the same way. 
    Console.WriteLine(hashtable.Contains("Area")); 

    // Get value of Area with indexer. 
    int value = (int)hashtable["Area"]; 

    // Write the value of Area. 
    Console.WriteLine(value); 
    } 
} 

Выходной

True 
True 
1000 

Индексатор это свойство, которое получает аргумент внутри квадратных скобок. В Hashtable реализованы индексы. Он возвращает простые объекты, поэтому вы должны их бросить. Дополнительную информацию см. В разделе литья.

Индексатор Несколько типов Далее, мы добавим несколько типов в Hashtable. В этом примере добавляются строковые ключи и клавиши int. Каждая из пар ключ/значение имеет разные типы. Вы можете поместить их все в одну Hashtable.

Программа, которая использует несколько типов [C#]

using System; 
using System.Collections; 

class Program 
{ 
    static Hashtable GetHashtable() 
    { 
    Hashtable hashtable = new Hashtable(); 

    hashtable.Add(300, "Carrot"); 
    hashtable.Add("Area", 1000); 
    return hashtable; 
    } 

    static void Main() 
    { 
    Hashtable hashtable = GetHashtable(); 

    string value1 = (string)hashtable[300]; 
    Console.WriteLine(value1); 

    int value2 = (int)hashtable["Area"]; 
    Console.WriteLine(value2); 
    } 
} 

Выход

Carrot 
1000 

Этот код может бросить исключения. Кастинг - деликатная операция. Если приведение было применено к другому типу, оператор может вызвать InvalidCastException. Вы можете избежать этого, используя инструкции is или as.

Вы можете избежать проблем с литьем в своей Hashtable. Вы можете использовать as-operator, чтобы попытаться применить объект к определенному ссылочному типу. Если приведение не выполняется, результат будет равен нулю.

Null Совет: Вы также можете использовать это-оператор. Этот оператор возвращает true или false на основе результата.

Является Как Программа, которая отбрасывает Hashtable значения [C#]

using System; 
using System.Collections; 
using System.IO; 

class Program 
{ 
    static void Main() 
    { 
    Hashtable hashtable = new Hashtable(); 
    hashtable.Add(400, "Blazer"); 

    // This cast will succeed. 
    string value = hashtable[400] as string; 
    if (value != null) 
    { 
     Console.WriteLine(value); 
    } 

    // This cast won't succeed, but won't throw. 
    StreamReader reader = hashtable[400] as StreamReader; 
    if (reader != null) 
    { 
     Console.WriteLine("Unexpected"); 
    } 

    // You can get the object and test it. 
    object value2 = hashtable[400]; 
    if (value2 is string) 
    { 
     Console.Write("is string: "); 
     Console.WriteLine(value2); 
    } 
    } 
} 

Выход

Blazer является строка: Blazer

С Hashtable, вы можете уменьшить количество слепков и повысить производительность, используя оператор as-operator. Это одно предупреждение о производительности, данное FxCop, инструментом статического анализа от Microsoft.

FXCop * ключи, значения * Далее мы получаем все ключи или значения. Мы можем перебрать эти значения или сохранить их в отдельной коллекции ArrayList. В этом примере показаны все ключи, затем все значения, а затем хранятся ключи в ArrayList.

Примечание: В этом примере C# Hashtable используется свойство Keys. Это свойство возвращает все ключи.

Цикл по ключам, ценности и хранить в ArrayList [C#]

using System; 
using System.Collections; 

class Program 
{ 
    static void Main() 
    { 
    Hashtable hashtable = new Hashtable(); 
    hashtable.Add(400, "Blaze"); 
    hashtable.Add(500, "Fiery"); 
    hashtable.Add(600, "Fire"); 
    hashtable.Add(800, "Immolate"); 

    // Display the keys. 
    foreach (int key in hashtable.Keys) 
    { 
     Console.WriteLine(key); 
    } 

    // Display the values. 
    foreach (string value in hashtable.Values) 
    { 
     Console.WriteLine(value); 
    } 

    // Put keys in an ArrayList. 
    ArrayList arrayList = new ArrayList(hashtable.Keys); 
    foreach (int key in arrayList) 
    { 
     Console.WriteLine(key); 
    } 
    } 
} 

Выходного

800  (First loop) 
600 
500 
400 
Immolate (Second loop) 
Fire 
Fiery 
Blaze 
800  (Third loop) 
600 
500 
400 

Looping над клавишами. Первый цикл в программе пересекает коллекцию, возвращаемую свойством экземпляра Keys в экземпляре Hashtable. Вы можете использовать цикл foreach для простейшего синтаксиса.

Цитирование по значениям. Второй цикл в программе показывает, как перечислять только значения в экземпляре Hashtable.Четыре слова, сохраненные в Hashtable как значения, будут напечатаны на экране.

Console.WriteLine Хранение в ArrayList. В примере создается новый ArrayList с конструктором копирования и передается в качестве аргумента свойство Keys (или Values). После выполнения конструктора ArrayList ArrayList может быть перечислит.

ArrayList

Совет: Ключи и значение общественных аксессоры возвращают коллекцию ключей и значений в Hashtable в то время они получают доступ.

Однако: Если вам нужно смотреть на все ключи и значения в парах, то лучше перечислить Хеш экземпляру себя.

граф Ясно

Вы можете рассчитывать элементы в Hashtable со свойством Count. В этом примере также показано использование метода Clear для удаления всего содержимого Hashtable. Альтернативой является переназначение вашей ссылки Hashtable на новую Hashtable().

Примечание: В этом примере показано, как использовать свойство Count. Это свойство возвращает количество элементов.

Программа, которая использует Рассчитывать на Hashtable [C#]

using System; 
using System.Collections; 

class Program 
{ 
    static void Main() 
    { 
    // Add four elements to Hashtable. 
    Hashtable hashtable = new Hashtable(); 
    hashtable.Add(1, "Sandy"); 
    hashtable.Add(2, "Bruce"); 
    hashtable.Add(3, "Fourth"); 
    hashtable.Add(10, "July"); 

    // Get Count of Hashtable. 
    int count = hashtable.Count; 
    Console.WriteLine(count); 

    // Clear the Hashtable. 
    hashtable.Clear(); 

    // Get Count of Hashtable again. 
    Console.WriteLine(hashtable.Count); 
    } 
} 

Выход

4 
0 

Во-первых, программа добавляет четыре клавиши с четырьмя значениями в Hashtable инстанции. Затем он захватывает граф, который равен 4. Затем он использует Clear на Hashtable, который теперь имеет 0 элементов. Hashtable пуст, но не null.

Count property on Hashtable. Класс Hashtable реализует средство доступа к объекту открытого экземпляра, которое возвращает количество элементов в Hashtable. Свойство Count не выполняет длительных вычислений или циклов.

Примечание: MSDN заявляет, что для Count «получение значения этого свойства является операцией O (1)».

Постоянное время. Это свойство является постоянным аксессуаром. Он сообщит, что Hashtable имеет несколько фактических элементов в своих ведрах (или ноль). Он возвращает целое число и представляет собой простой аксессуар с низкими потребностями в ресурсах.

Benchmark

Продолжая, мы тестируем Hashtable коллекции в пространстве имен System.Collections против словаря коллекции в пространстве имен System.Collections.Generic. Сначала эталон заполняет эквивалентную версию каждой коллекции.

Then: Он проверяет один найденный ключ и тот, который не найден. Он повторяет это 20 миллионов раз.

Hashtable используется в тесте [C#]

Hashtable hashtable = new Hashtable(); 
for (int i = 0; i < 10000; i++) 
{ 
    hashtable[i.ToString("00000")] = i; 
} 

Dictionary used in benchmark [C#] 

var dictionary = new Dictionary<string, int>(); 
for (int i = 0; i < 10000; i++) 
{ 
    dictionary.Add(i.ToString("00000"), i); 
} 

Statements benchmarked [C#] 

hashtable.ContainsKey("09999") 
hashtable.ContainsKey("30000") 

dictionary.ContainsKey("09999") 
dictionary.ContainsKey("30000") 

контрольный показатель в 20 миллионов операций поиска

Hashtable result: 966 ms 
Dictionary result: 673 ms 

Хеш-код значительно медленнее, чем словарь кода. Я подсчитал, что Hashtable здесь на 30% медленнее. Это означает, что для сильно типизированных коллекций Словарь быстрее.

Конструкторы

Есть 15 перегруженные конструкторы в Hashtable класса. Они обеспечивают способы определения пропускной способности. Они позволяют копировать существующие коллекции в Hashtable. Вы также можете указать, как вычисляется хэш-код.

Конструктор Советы Резюме

Мы использовали Hashtable коллекции. Это более старая коллекция, устаревшая из коллекции Dictionary. Знание того, как его использовать, имеет решающее значение при сохранении старых программ. Эти программы важны для многих организаций.

+0

Я знаю, как работает хеш-таблица. Я знал это, даже когда задавал вопрос. Более того, этот ответ никоим образом не пытается ответить на мой реальный вопрос. Кроме того, вы не получаете баллов за копирование с другого сайта (http://www.dotnetperls.com/hashtable). Если вам нечего сказать, кроме какой-либо другой веб-страницы, просто разместите ссылку в комментарии по этому вопросу. –

 Смежные вопросы

  • Нет связанных вопросов^_^