Tuesday, December 7, 2010

Наследование классов (часть 1)

Предположим, что у нас есть два объекта – Door (дверь) и Window (окно). Каждый из них имеет методы Open (открыть) и Close (закрыть):
Class Door
{
  private bool isOpened;
  public void Open()
  {
    isOpened=true;
  }
  public void Close()
  {
    isOpened=false;
  }
}
Точно такой же код содержится в классе Window. Проблема именно в “точно такой же” – при необходимости модифицировать этот код нам придется найти все его вхождения и исправить. Не факт что мы найдем все.
Наследование позволяет, во-первых, избавиться от дублирования кода, вынести его в общее место.
class BaseObject
{
  private bool isOpened;
  public void Open()
  {
    isOpened=true;
  }
  public void Close()
  {
    isOpened=false;
  }
}
class Door : BaseObject
{
  // методы Open и Close доступны
  // они придут сюда из базового объекта
}
class Window : BaseObject
{
}
Во-вторых, наследование выстраивает логические связи между объектами, облегчая их понимание. Вместо кучи разрозненных классов, мы получаем осмысленную структуру (иерархию классов). Разумеется, эта иерархия должна отражать логические связи, иначе, она будет не понятна. Например, класс Бутылка тоже может иметь методы Открыть и Закрыть, но наследовать его от базового объекта СтроительныеМатериалы, не очень логично.
Класс BaseObject, от которого происходит наследование, называется базовым классом.
Классы Door и Window называются наследниками (потомками) класса BaseObject.
Замечу, что в C++ и многих других языках, можно было реализовать класс, наследующий несколько классов, но в C# такую возможность закрыли. Сделали это специально, т.к. множественное наследование вызывало ошибки.
В C# абсолютно все типы наследуются от специального типа System.Object.
Итак, первые два плюса наследования:
1. Сокращение дублирования кода
2. Создание логических связей между объектами.
Продолжение следует.

Monday, December 6, 2010

Уменьшайте вложенность if-ов

Код вида

  if (условие)  {
      два листа кода
  }
  else
  {
    return false;
  }


читать крайне не удобно. Листаешь, листаешь... а тут return. Лучше писать

 if (!условие)
   return false;
 два листа кода

И читать удобнее и код направо не уезжает.

101 пример LINQ выражений

Очень полезный набор примеров

http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx

Saturday, December 4, 2010

Работа с битовыми полями

В C# для работы с битовыми полями предусмотрен класс BitVector32. Этот класс более эффективен, чем BitArray.

using System;
using System.Collections.Specialized;


namespace BitVector32Test
{
  class Class1
  {
    [STAThread]
    static void Main(string[] args)
    {
      BitVector32 vector1 = new BitVector32( 0 );

      // Маски для первых пяти битов
      int bit1 = BitVector32.CreateMask();
      int bit2 = BitVector32.CreateMask(bit1);
      int bit3 = BitVector32.CreateMask(bit2);
      int bit4 = BitVector32.CreateMask(bit3);
      int bit5 = BitVector32.CreateMask(bit4);

      // Получаем BitVector32{00000000000000000000000000000000}
      Console.WriteLine(vector1.ToString());
      vector1[bit1] = true; // установить 1 бит
      // Получаем BitVector32{00000000000000000000000000000001}
      Console.WriteLine(vector1.ToString());
      vector1[bit3] = true; // установить 3 бит
      // Получаем BitVector32{00000000000000000000000000000101}
      Console.WriteLine(vector1.ToString());
      vector1[bit5] = true; // установить 5 бит
      // Получаем BitVector32{00000000000000000000000000010101}
      Console.WriteLine(vector1.ToString());

      BitVector32 vector2 = new BitVector32( 0 );
      // Создаем 4 секции. Первая имеет максимум
      // значений 6, т. е занимает 4 бита. Вторая - максимум 3
      // (т. е. два бита), затем 1 бит, затем 4 бита.
      BitVector32.Section sect1 = BitVector32.CreateSection( 6 );
      BitVector32.Section sect2 =
                       BitVector32.CreateSection( 3, sect1 );
      BitVector32.Section sect3 =
                       BitVector32.CreateSection( 1, sect2 );
      BitVector32.Section sect4 =
                       BitVector32.CreateSection(15, sect3 );

      vector2[sect2] = 3;
      // Получим BitVector32{00000000000000000000000000011000}
      Console.WriteLine(vector2.ToString());
      vector2[sect4] = 1;
      // Получим BitVector32{00000000000000000000000001011000}
      Console.WriteLine(vector2.ToString());
    }
  }
}

Friday, December 3, 2010

Thread-safe словарь

В .Net до версии 3 приходилось словари, доступные для работы в потоках, делать руками. В версии 4 появился удобный класс ConcurrentDictionary. Он находится в пространстве имен System.Collections.Concurrent. Правда к его методам нужно привыкнуть. Например, вместо простого Add здесь bool TryAdd(), который вернет false, если такой ключ уже есть. Аналогично - TryRemove, TryGetValue, TryUpdate.

Обновить значения в hashtable в цикле

Если попробовать изменять значения hashtable во время перебора элементов в цикле, то будет сгенерировано исключение.

Обойти это можно так:

foreach (object key in new List<object>(dataTable.Keys.Cast<object>()))
    dataTable[key] = null;

Wednesday, December 1, 2010

Цитата

В стрессовой ситуации для того, чтобы сохранить спокойствие, достаточно создать в Word файл "спокойствие" и кликнуть на кнопку "сохранить".