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

 Рассмотрим такую ситуацию: у нас есть главная сборка (Main), сборка с утилитными классами (Utils) и 3-rd party логгер (Logger):

 

При этом Utils достался нам ещё со староко проекта и мы просто подключили его проект в наш solution, а логгер - соответствующий компонент из Microsoft Enterprise Library.
 
Решение этой задачи разбивается на следующие шаги:
  1. Добавляем в наш solution нужные нам проекты.
  2. Добавляем ссылки на проекты.
Почему-то, некоторые выбирают такой способ решения: выполняют шаг 1 - тут у нас только один способ сделать это (я не беру в счёт способ ручного редактирования *proj-файла), Build -> Rebuild Solution, и собственно добавление ссылки на проект путём добавления ссылки на dll:


В таком случае, если вам сильно повезёт и такого в вашем solution будет не много, достаточно будет сначала сделать Build -> Rebuild Solution, после чего всё заработает, а если не повезёт... А если не повезёт прийдётся ещё руками настраивать project dependecies и писать не менее захватывающий сценарий для билдов.
 
Теперь рассмотрим как это делать правильно:
Добавляем ссылку не на сборку, а на проект в solution:
 

 
После чего всё выглядит так:
 
Таким образом все зависимости на проекты выставляются автоматически и нам больше не нужен бубун для сборки solution и билдов.
 
Осталось подключись сборку с логгером. Но и здесь не всё так просто. В случае с Enterprise Library достаточно добавить ссылка на сборку из GAC:

У этого спосоа есть несколько недостатков: Enterprise Library должна быть установлена на всех машинах, где будет запускиться проект, и везде должна быть одна и таже версия. Второй недостаток хорошо ощёщается если использовать библиотеки, которые достаточно быстро развиваются и имеют множество версий (e.g. NUnit. AjaxControlToolkit, etc).
 
Я предпочитаю другой способ решения этой задачи (не могу сказать, что он не имеет недостатков, но, лично для меня, его преимущества имеют больший вес).
Все сторонние библиотеки кладутся в Source Control и уже на них ссылаются все проекты. Для удобства можно ещё создать папку в solution:

ReferencesSample.zip (76.14 kb)


На проекте приходится использовать SourceGear Vault - source control система, которая очень похожа на VSS. Сегодня наткнулся на очередной глюк:

 

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

Те, кто знает на память книгу Дж.Рихтера C# via .NET, в этом врядли найдут для себя что-то новое/интересное.
 

 Всё началось с того, что было у меня два похожих enum'ов (к примеру Numbers и BigNumbers) и нужно было как-то переменные первого типа приводить к другом, и наоборот. 

enum Numbers
    {
        One,
        Two,
        Three
    }

    enum BigNumbers
    {
        One,
        Two,
        Three,
        Four,
        Five
    }

На практике такие преобразования выглядят примерно так :

Numbers n1 = Numbers.One;
Numbers n2 = (Numbers) 2;
Int32 i1 = (Int32) n1;

BigNumbers b1 = BigNumbers.Five;

Numbers n3 = (Numbers) b1;

Console.WriteLine(String.Format("n1 = {0}", n1));
Console.WriteLine(String.Format("n2 = {0}", n2));
Console.WriteLine(String.Format("i1 = {0}", i1));
Console.WriteLine(String.Format("b1 = {0}", b1));
Console.WriteLine(String.Format("n3 = {0}", n3));
 

В результате на экране мы получим следующее:

n1 = One
n2 = Three
i1 = 0
b1 = Five
n3 = 4 

  Здесь мы видим, что n3 теперь равняется 4-м. Логичный, но не совсем ожидаемый для меня результат. В таком случае хотелось бы получить какой-то Exception.

 Теперь разберёмся что представляет собой enum и почему он так работает.

Enum (перечесляемый тим, enumerated type) предоставляет нам возможность хранить пару имя-значение и пришли в дополнение к константом (например: вместо того, чтоб в методе возвращать код ошибки, можно создать enum с именами ошибок).  По сути, System.Enum представляет обёкт размерного (value) типа, пронаследованного от System.ValueType:

 public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible


И, по умолчию, запись  "enum Numbers" соответствует "enum Numbers : int". В этом можно убедится, посмотрев на наше приложение с помощью IL DASM, который входит в комплект поставки .NET Framework SDK.

.class private auto ansi sealed Enums.Numbers       extends [mscorlib]System.Enum{} // end of class Enums.Numbers
.field public static literal valuetype Enums.Numbers One = int32(0x00000000)

 
Таким образом мы видим, что все элементы нашего enum являются целыми числами (int). Вместо int, можно указать byte, sbyte, short, ushort, int, long, и ulong. Интересно что если указать имя типа так, как они именуются в FCL (Byte, Int32 и т.д.), то мы получим ошибку: 
 Type byte, sbyte, short, ushort, int, uint, long, or ulong expected
 
 
Вернёмся к нашему примеру. Чтоб в нём всё работало так, как ожидалось, достаточно добавить такой код:

 if (!Enum.IsDefined(typeof(Numbers), b1)){throw new ArgumentException();}

 

Enums.zip (3.01 kb)


Решая на первый взгляд простую задачу я столкнулся с некоторыми поблемами. Задача состоит в том, чтобы из массива удалить один из его элементов. Оказалось, что стандартными средствами JavaScript этого не сделать.

Итак, у нас есть исходный массив:

var arr = new Array();
arr.push('q');
arr.push('w');
arr.push('a');
arr.push('e');
arr.push('r');
arr.push('t');
arr.push('z');
arr.push('y'); 

 Задача состоит в том, чтобы удалить из него элементы со значениями "a" и "z". Первой же идеей было использование оператора delete:

var i = arr.indexOf('a');
delete arr[i];
i = arr.indexOf('z');
delete arr[i];

 И было вы всё хорошо, еслиб не реализация этого самого оператора delete: элементы из массива на самом не удаляются, просто их значение стоновится undefined и, соответственно, свойство lenght не меняется. Можно, конечно, при обходе массива проверять значение элементов и таким образом проверять, удалённый он или нет, но в моём случае это несло за собой изменение логики на сервере, что делать не хотелось и было принято решение реализовать нужную функциональность в классе Array:

Array.prototype.removeByValue = function(item){
        var itemIndex = -1;
        for (var index = 0; index < this.length; index++)
        {
            if (this[index] == item){
                itemIndex=index;
            }
        }
        
        if (itemIndex == -1){
            return this;
        }
        
        var resultLeft = this.slice(0, itemIndex);
        var resultRight = this.slice(itemIndex+1, this.length);
        var resultTotal = resultLeft.concat(resultRight);

        return resultTotal;

 };

 Способ использования:

var a = arr.removeByValue('a'); 
arr = a.removeByValue('z'); 

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