Рекомендации GetHashCode в C #

Я прочитал в книге Essential C # 3.0 и .NET 3.5, что:

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

Это действующее руководство?

Я пробовал пару встроенных типов в .NET, и они не вели себя так.


person Joan Venge    schedule 20.01.2009    source источник
comment
Возможно, вы захотите изменить принятый ответ, если это возможно.   -  person Giffyguy    schedule 23.09.2015


Ответы (9)


Ответ в основном таков: это действительное руководство, но, возможно, не действительное правило. Это также не говорит всей истории.

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

Например, объект A возвращает хэш 1. Итак, он попадает в корзину 1 хеш-таблицы. Затем вы изменяете объект A таким образом, чтобы он возвращал хеш-значение 2. Когда хеш-таблица ищет его, она ищет его в корзине 2 и не может найти - объект находится в корзине 1. Вот почему хеш-код должен не менять на время существования объекта, и это лишь одна из причин, по которой написание реализаций GetHashCode является головной болью.

Обновление
Эрик Липперт разместил блог, в котором содержится отличная информация о GetHashCode.

Дополнительное обновление
Я внес несколько изменений выше:

  1. Я проводил различие между руководством и правилом.
  2. Я зачеркнул «на время жизни объекта».

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

Когда вы видите «на время существования объекта», вы должны прочитать «на время, в течение которого объект должен взаимодействовать с хеш-таблицами» или что-то подобное. Как и большинство других вещей, GetHashCode означает знать, когда нарушать правила.

person Jeff Yates    schedule 20.01.2009
comment
Как определить равенство изменяемых типов? - person Jon B; 20.01.2009
comment
Вы не должны использовать GetHashCode для определения равенства. - person JSBձոգչ; 20.01.2009
comment
@JS Bangs - Из MSDN: производные классы, которые переопределяют GetHashCode, также должны переопределять Equals, чтобы гарантировать, что два объекта, которые считаются равными, имеют одинаковый хэш-код; в противном случае тип Hashtable может работать некорректно. - person Jon B; 20.01.2009
comment
Спасибо. Интересный момент, но когда я примеряю его, скажем, тип Point, изменение X или Y возвращает другой хэш-код, чем до его изменения. Почему команда .NET проигнорировала это, потому что в Point есть изменяемые данные. - person Joan Venge; 20.01.2009
comment
@ Джоан Венге: Две вещи. Во-первых, даже Microsoft не имеет права GetHashCode при каждой реализации. Во-вторых, типы значений обычно неизменяемы, и каждое значение является новым экземпляром, а не модификацией существующего экземпляра. - person Jeff Yates; 20.01.2009
comment
System.Drawing.Point не является неизменным. Вы можете изменить свойства X и Y, и это приведет к другому хэш-коду. - person Jon B; 20.01.2009
comment
Спасибо, Джефф, это имеет смысл. Так, скажем, для типа Point, когда я меняю X, он создает новое значение Point и присваивает себе? - person Joan Venge; 20.01.2009
comment
Нет, Point, к сожалению, изменчив и нарушает правила GetHashCode, как только что указал Джон Б. Как я уже сказал, даже Microsoft не поняла это правильно. - person Jeff Yates; 20.01.2009
comment
Спасибо, парни. Тогда можно с уверенностью предположить, что, вероятно, существует больше типов с плохой реализацией GetHashCode, подобной этой, верно? Знаете ли вы какой-либо тип типа Point, который является изменяемым, но имеет правильную реализацию GetHashCode? - person Joan Venge; 20.01.2009
comment
Это серьезная проблема, только если вы собираетесь использовать тип в ситуациях, требующих действительного хеша (например, в HashTable). в этом случае проще всего было бы обернуть тип Point в свой собственный неизменяемый вариант, который каким-то образом достигает трех целей GetHashCode. - person Jeff Yates; 20.01.2009
comment
Спасибо. А как насчет таких типов, как тип Point, которые изменяются, но имеют правильную реализацию GetHashCode? Я просто хочу их осмотреть? - person Joan Venge; 20.01.2009
comment
Point имеет неверный GetHashCode, если он изменяемый, и GetHashCode возвращает другое значение, когда экземпляр изменен. - person Jeff Yates; 20.01.2009
comment
Извините, что я хотел сказать, типы в отличие от Point, где у них есть правильная реализация GetHashCode. Вы знаете что-нибудь из этого? Но у него все еще должны быть изменяемые члены, чтобы я мог видеть, как они с этим справляются. - person Joan Venge; 20.01.2009
comment
Что ж, структура делает это для ссылочных типов, просто используя счетчик, который, как мне кажется, увеличивается на единицу для каждого объекта. Но это не соответствует правилу случайного распределения. Вы можете сгенерировать случайное число, но я не знаю, целесообразно ли это. Кто-нибудь знает? - person Jeff Yates; 20.01.2009
comment
Если вы сгенерируете случайное число, то объекты с равными значениями не будут иметь одинаковых хэш-кодов. - person Jon B; 20.01.2009
comment
Как насчет генерации случайного числа, но для сравнения Equals использовать фактические значения, такие как X и Y? Это сработает? - person Joan Venge; 20.01.2009
comment
Ах, вот тут-то и возникает трудность. - person Jeff Yates; 20.01.2009
comment
Неплохо. Есть ли хотя бы хороший образец, который я могу использовать в качестве основы? Может быть, есть такой тип, чтобы вы могли хотя бы имитировать то же самое, что было бы очень хорошо. В любом случае, идея, которую я предложил, осуществима? - person Joan Venge; 21.01.2009
comment
Если вам нужен изменяемый тип, который можно использовать в HashTable, вам нужно заморозить мутацию, пока объект находится в хеш-таблице, если только хеш не привязан к изменяемым свойствам. Однако, если изменяемые свойства участвуют в равенстве, они также должны влиять на хеш. Тем не мение... - person Jeff Yates; 21.01.2009
comment
... помните, что хотя два одинаковых экземпляра должны иметь одинаковый хеш, не все экземпляры с одинаковым хешем равны. - person Jeff Yates; 21.01.2009
comment
Как реализовать равенство для изменяемого объекта ссылочного типа? просмотрите stackoverflow.com/questions / 2626547 / - person Shimmy Weitzhandler; 13.04.2010
comment
@Shimmy: Вам следует восстановить свой вопрос и ответ; в будущем они могут быть полезны другому программисту, который столкнется с той же проблемой и хочет найти решение, подобное тому, которое вы нашли. - person Jeff Yates; 13.04.2010
comment
Прошу прощения, это была ошибка, я переместил вопрос: stackoverflow.com/questions/2626839/ - person Shimmy Weitzhandler; 13.04.2010
comment
Поскольку a.Equals (b) должно означать, что a.GetHashCode () == b.GetHashCode (), хэш-код чаще всего должен изменяться, если данные, используемые для сравнения на равенство, изменяются. Я бы сказал, что проблема не в том, что GetHashCode основан на изменяемых данных. Проблема заключается в использовании изменяемых объектов в качестве ключей хеш-таблицы (и фактическом их изменении). Я ошибся? - person Niklas; 21.12.2010
comment
@Niklas: Да, это проблема. Я не уверен, что могу пойти так далеко, чтобы сказать, что была только одна проблема. В конце концов, все зависит от того, чего вы пытаетесь достичь, но, исходя из правил, хэш-код не должен изменяться в течение всего времени существования объекта - но, как вы и другие отмечаете, это действительно проблема только тогда, когда фактически используется хэш-код, например, в хеш-таблице. - person Jeff Yates; 21.12.2010
comment
Сообщение @Jeff Yates Эрика Липпертса отличное. Спасибо! - person Orhan Cinar; 14.07.2011
comment
@ Орхан: Нет проблем. Это мой путеводитель по GetHashCode. - person Jeff Yates; 14.07.2011
comment
Рекомендация Эрика Липперта значительно отличается от указанной в вопросе. Указание в вопросе неверно. @Jeff, ваши последующие комментарии показывают понимание этого. Не могли бы вы обновить свой ответ? - person Neil; 14.07.2011
comment
@Neil: Надеюсь, я сделал пару правок, чтобы прояснить ситуацию. - person Jeff Yates; 15.07.2011
comment
Вы должны выделить последний абзац жирным шрифтом! В этом его суть. Не многие осознают это. - person nawfal; 09.11.2013

Прошло много времени, но, тем не менее, я думаю, что все же необходимо дать правильный ответ на этот вопрос, в том числе объяснить, почему и как. Лучшим ответом на данный момент является тот, который исчерпывающе цитирует MSDN - не пытайтесь устанавливать свои собственные правила, ребята из MS знали, что они делают.

Но обо всем по порядку: Руководство, указанное в вопросе, неверно.

Теперь почему - их два

Во-первых, почему: если хэш-код вычисляется таким образом, что он не изменяется в течение времени существования объекта, даже если сам объект изменяется, это нарушит контракт равенства.

Помните: «Если два объекта сравниваются как равные, метод GetHashCode для каждого объекта должен возвращать одно и то же значение. Однако, если два объекта не сравниваются как равные, методы GetHashCode для двух объектов не должны возвращать разные значения».

Второе предложение часто ошибочно интерпретируется как «Единственное правило состоит в том, что во время создания объекта хэш-коды одинаковых объектов должны быть одинаковыми». Не знаю, почему, но это и есть суть большинства ответов здесь.

Подумайте о двух объектах, содержащих имя, где имя используется в методе equals: То же имя -> то же самое. Создать экземпляр A: Name = Joe Создать экземпляр B: Name = Peter

Хэш-код A и Hashcode B, скорее всего, не будут одинаковыми. Что теперь произойдет, если имя экземпляра B будет изменено на Joe?

Согласно руководству из вопроса, хэш-код B не изменится. Результатом этого будет: A.Equals (B) ==> true Но в то же время: A.GetHashCode () == B.GetHashCode () ==> false.

Но именно такое поведение явно запрещено контрактом equals & hashcode.

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


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

Источник проблем хорошо описан в MSDN:

Из записи хеш-таблицы MSDN:

Ключевые объекты должны быть неизменными, пока они используются в качестве ключей в Hashtable.

Это означает:

Любой объект, который создает хэш-значение, должен изменять хеш-значение при изменении объекта, но он не должен - абсолютно не должен - допускать никаких изменений самого себя, когда он используется внутри Hashtable (или, конечно, любого другого объекта, использующего хэш) .

Во-первых, как проще, конечно, было бы разработать неизменяемые объекты только для использования в хэш-таблицах, которые при необходимости будут создаваться как копии обычных изменяемых объектов. Внутри неизменяемых объектов вполне нормально кэшировать хэш-код, поскольку он неизменяемый.

Во-вторых, как Или дайте объекту флаг «вы сейчас хешированы», убедитесь, что все данные объекта являются приватными, проверьте флаг во всех функциях, которые могут изменять данные объектов, и выдать данные исключения, если изменение не разрешено (т. Е. Установлен флаг ). Теперь, когда вы помещаете объект в любую хешированную область, обязательно установите флаг, а также снимите флаг, когда он больше не нужен. Для простоты использования я бы посоветовал установить флаг автоматически внутри метода GetHashCode - таким образом его нельзя забыть. А явный вызов метода «ResetHashFlag» гарантирует, что программисту придется подумать, разрешено или не разрешено изменять данные объекта на данный момент.

Хорошо, что также следует сказать: есть случаи, когда возможно иметь объекты с изменяемыми данными, когда хэш-код, тем не менее, не изменяется, когда данные объекта изменяются, без нарушения контракта equals & hashcode.

Однако это требует, чтобы метод equals также не основывался на изменяемых данных. Итак, если я напишу объект и создаю метод GetHashCode, который вычисляет значение только один раз и сохраняет его внутри объекта, чтобы вернуть его при последующих вызовах, тогда я снова должен: абсолютно необходимо создать метод Equals, который будет использовать сохраненные значения для сравнения, так что A.Equals (B) также никогда не изменится с false на true. В противном случае контракт был бы разорван. Результатом этого обычно будет то, что метод Equals не имеет никакого смысла - это не исходная ссылка, равная, но и не равная по значению. Иногда это может быть запланированное поведение (например, записи о клиентах), но обычно это не так.

Итак, просто измените результат GetHashCode, когда данные объекта изменяются, и если использование объекта внутри хэша с использованием списков или объектов предполагается (или только возможно), тогда сделайте объект либо неизменяемым, либо создайте флаг только для чтения для использования для время жизни хешированного списка, содержащего объект.

(Между прочим: все это не относится к C # или .NET - это характерно для всех реализаций хэш-таблиц или, в более общем смысле, для любого индексированного списка, что идентифицирующие данные объектов никогда не должны изменяться, пока объект находится в списке . Неожиданное и непредсказуемое поведение произойдет, если это правило будет нарушено. Где-то могут быть реализации списков, которые отслеживают все элементы внутри списка и выполняют автоматическую переиндексацию списка - но производительность этих элементов наверняка будет в лучшем случае ужасной.)

person Alex    schedule 13.07.2010
comment
+1 за это подробное объяснение (дал бы больше, если бы мог) - person Oliver; 13.07.2010
comment
+1 это определенно лучший ответ из-за подробного объяснения! :) - person Joe; 25.02.2011

Из MSDN

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

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

Для лучшей производительности хеш-функция должна генерировать случайное распределение для всех входных данных.

Это означает, что если значение (я) объекта изменится, хэш-код должен измениться. Например, класс «Человек» со свойством «Имя», установленным на «Том», должен иметь один хэш-код и другой код, если вы измените имя на «Джерри». В противном случае Том == Джерри, что, вероятно, не то, что вы хотели.


Изменить:

Также из MSDN:

Производные классы, которые переопределяют GetHashCode, также должны переопределять Equals, чтобы гарантировать, что два объекта, которые считаются равными, имеют одинаковый хэш-код; в противном случае тип Hashtable может работать некорректно.

Из записи в хэш-таблице MSDN:

Ключевые объекты должны быть неизменными, пока они используются в качестве ключей в Hashtable.

Насколько я понимаю, изменяемые объекты должны возвращать разные хэш-коды при изменении их значений, если они не предназначены для использования в хэш-таблице.

В примере System.Drawing.Point объект является изменяемым, и действительно возвращает другой хэш-код при изменении значения X или Y. Это сделало бы его плохим кандидатом для использования в хэш-таблице.

person Jon B    schedule 20.01.2009
comment
GetHashCode () предназначен для использования в хэш-таблице, и это единственная особенность этой функции. - person skolima; 17.06.2010
comment
@skolima - документация MSDN с этим не согласуется. Изменяемые объекты могут реализовывать GetHashCode () и должны возвращать разные значения при изменении значения объекта. Хеш-таблицы должны использовать неизменяемые ключи. Следовательно, вы можете использовать GetHashCode () для чего-то другого, кроме хеш-таблицы. - person Jon B; 17.06.2010

Я думаю, что документация по GetHashcode немного сбивает с толку.

С одной стороны, MSDN заявляет, что хэш-код объекта никогда не должен изменяться и быть постоянным. С другой стороны, MSDN также заявляет, что возвращаемое значение GetHashcode должно быть равным для 2 объектов, если эти 2 объекта считаются равными.

MSDN:

Хеш-функция должна иметь следующие свойства:

  • Если два объекта сравниваются как равные, метод GetHashCode для каждого объекта должен возвращать одно и то же значение. Однако, если два объекта не сравниваются как равные, методы GetHashCode для двух объектов не должны возвращать разные значения.
  • Метод GetHashCode для объекта должен последовательно возвращать один и тот же хэш-код до тех пор, пока не будет изменено состояние объекта, определяющее возвращаемое значение метода Equals объекта. Обратите внимание, что это верно только для текущего выполнения приложения и что другой хэш-код может быть возвращен, если приложение запускается снова.
  • Для лучшей производительности хеш-функция должна генерировать случайное распределение для всех входных данных.

Тогда это означает, что все ваши объекты должны быть неизменяемыми или метод GetHashcode должен основываться на неизменяемых свойствах вашего объекта. Предположим, например, что у вас есть этот класс (наивная реализация):

public class SomeThing
{
      public string Name {get; set;}

      public override GetHashCode()
      {
          return Name.GetHashcode();
      }

      public override Equals(object other)
      {
           SomeThing = other as Something;
           if( other == null ) return false;
           return this.Name == other.Name;
      }
}

Эта реализация уже нарушает правила, которые можно найти в MSDN. Предположим, у вас есть 2 экземпляра этого класса; для свойства Name экземпляра instance1 установлено значение «Pol», а для свойства Name экземпляра instance2 установлено значение «Piet». Оба экземпляра возвращают другой хэш-код, и они также не равны. Теперь предположим, что я изменяю имя instance2 на «Pol», тогда, согласно моему методу Equals, оба экземпляра должны быть равны, и согласно одному из правил MSDN они должны возвращать один и тот же хэш-код.
Однако , этого сделать нельзя, так как хэш-код instance2 изменится, а MSDN заявляет, что это запрещено.

Затем, если у вас есть сущность, вы могли бы реализовать хэш-код так, чтобы он использовал «первичный идентификатор» этой сущности, который в идеале может быть суррогатным ключом или неизменяемым свойством. Если у вас есть объект значения, вы можете реализовать хэш-код, чтобы он использовал «свойства» этого объекта значения. Эти свойства составляют «определение» объекта значения. Это, конечно, природа ценностного объекта; вас интересует не его идентичность, а его ценность.
И, следовательно, объекты-значения должны быть неизменяемыми. (Как и в платформе .NET, строка, дата и т. Д. Являются неизменяемыми объектами).

Еще одна вещь, которая приходит в голову:
Во время какого «сеанса» (я действительно не знаю, как это назвать) должен «GetHashCode» возвращать постоянное значение. Предположим, вы открываете свое приложение, загружаете экземпляр объекта из БД (сущность) и получаете его хэш-код. Он вернет определенное число. Закройте приложение и загрузите ту же сущность. Требуется ли, чтобы на этот раз хэш-код имел то же значение, что и при первой загрузке объекта? ИМХО нет.

person Frederik Gheysels    schedule 20.01.2009
comment
Ваш пример объясняет, почему Джефф Йейтс говорит, что вы не можете основывать хэш-код на изменяемых данных. Вы не можете вставить изменяемый объект в Словарь и ожидать, что он будет хорошо работать, если хеш-код основан на изменяемых значениях этого объекта. - person Ogre Psalm33; 07.04.2009
comment
Я не вижу, где нарушено правило MSDN? Правило четко гласит: метод GetHashCode для объекта должен последовательно возвращать один и тот же хэш-код до тех пор, пока не будет никаких изменений в состоянии объекта, которое определяет возвращаемое значение метода Equals объекта. Это означает, что хэш-код instance2 можно изменить, когда вы измените имя instance2 на Pol. - person chikak; 25.11.2009

Это хороший совет. Вот что говорит по этому поводу Брайан Пепин:

Это несколько раз сбивало меня с толку: убедитесь, что GetHashCode всегда возвращает одно и то же значение в течение всего времени существования экземпляра. Помните, что хэш-коды используются для идентификации «корзин» в большинстве реализаций хеш-таблиц. Если "корзина" объекта изменяется, хеш-таблица может не найти ваш объект. Это могут быть очень сложные ошибки, поэтому исправьте их с первого раза.

person Justin R.    schedule 20.01.2009
comment
Я не голосовал против, но полагаю, что это сделали другие, потому что это цитата, которая не охватывает всей проблемы. Предположим, что строки были изменяемыми, но не изменили хэш-коды. Вы создаете bob, используете его как ключ в хеш-таблице, а затем меняете его значение на phil. Затем создайте новую струну phil. если вы затем поищете запись в хеш-таблице с ключом phil, элемент, который вы изначально вставили, не будет найден. Если бы кто-то поискал по bob, он был бы найден, но вы бы получили значение, которое больше не может быть правильным. Либо старайтесь не использовать изменяемые ключи, либо помните об опасностях. - person Eric Tuttleman; 15.12.2010
comment
@EricTuttleman: Если бы я писал правила для фреймворка, я бы указал, что для любой пары объектов X и Y после вызова X.Equals(Y) или Y.Equals(X) все будущие вызовы должны давать тот же результат. Если кто-то хочет использовать какое-то другое определение равенства, используйте EqualityComparer<T>. - person supercat; 22.01.2013

Не отвечая напрямую на ваш вопрос, но - если вы используете Resharper, не забывайте, что у него есть функция, которая генерирует разумную реализацию GetHashCode (а также метод Equals) для вас. Конечно, вы можете указать, какие члены класса будут учитываться при вычислении хэш-кода.

person petr k.    schedule 20.01.2009
comment
Спасибо, на самом деле я никогда не использовал Resharper, но я все время вижу, что он упоминается довольно часто, поэтому я должен попробовать. - person Joan Venge; 20.01.2009
comment
+1 Resharper, если он есть, генерирует красивую реализацию GetHashCode. - person ΩmegaMan; 18.12.2012

Посмотрите это сообщение в блоге Марка Брукса:

VTO, RTO и GetHashCode () - о, мой!

А затем ознакомьтесь с последующим постом (не могу ссылаться, поскольку я новичок, но есть ссылка в статье initlal), в котором обсуждается дальнейшее и рассматриваются некоторые незначительные недостатки в первоначальной реализации.

Это было все, что мне нужно было знать о создании реализации GetHashCode (), он даже предоставляет загрузку своего метода вместе с некоторыми другими утилитами, короче говоря, золото.

person Shaun    schedule 19.02.2010

Хэш-код никогда не меняется, но также важно понимать, откуда берется хэш-код.

Если ваш объект использует семантику значений, т.е. идентичность объекта определяется его значениями (например, String, Color, все структуры). Если идентификатор вашего объекта не зависит от всех его значений, то хэш-код идентифицируется подмножеством его значений. Например, ваша запись StackOverflow хранится где-то в базе данных. Если вы измените свое имя или адрес электронной почты, запись о клиенте останется прежней, хотя некоторые значения изменились (в конечном итоге вы обычно идентифицируетесь по длинному идентификатору клиента #).

Вкратце:

Семантика типа значения - хэш-код определяется значениями Семантика ссылочного типа - хэш-код определяется некоторым идентификатором

Я предлагаю вам прочитать Domain Driven Design Эрика Эванса, где он переходит к сущностям и типам значений (что более или менее то, что я пытался сделать выше), если это все еще не имеет смысла.

person DavidN    schedule 20.01.2009
comment
Это не совсем правильно. Для конкретного экземпляра хэш-код должен оставаться постоянным. В случае типов значений часто бывает так, что каждое значение является уникальным экземпляром, и поэтому хэш кажется измененным, но на самом деле это новый экземпляр. - person Jeff Yates; 20.01.2009
comment
Вы правы, типы значений неизменяемы, поэтому они не допускают изменений. Хороший улов. - person DavidN; 21.01.2009

Ознакомьтесь с рекомендациями и правилами для GetHashCode Эрика Липперта.

person Ian Ringrose    schedule 01.03.2011