Вчера, в очередной раз столкнувшись с интересным поведением кода, я решил привести пару примеров из C# и MS SQL, которые в свое время меня удивили.
С этим поведением я встретился несколько лет назад, когда только начал изучать C#. Применив знакомый метод, чтобы поменять значения 2-х переменных местами, я с удивлением обнаружил, что он не работает.
В итоге, в первый раз все проходит нормально и значения переменных меняются, а во второй раз, вопреки ожиданиям, у нас обнуляется переменная x.
Вот пример того, как функции cast и convert могут приподносить сюрпризы.
Хотя такое поведение и задокументировано в MSDN, столкнулся я с этим раньше чем прочитал о нем.
Этот пример также описан в MSDN, но узнал я о таком поведении, только когда из-за него произошла ошибка в программе.
В отличие от IN, который просто пропускает null, NOT IN всегда возвращает пустую выборку. В общем-то, после небольших размышлений, на тему «почему так?», результат уже не кажется необычным.
Следующая ситуация мне кажется необычной, потому что меняет поведение в зависимости от того, ловите ли вы исключение или нет.
Итак, напишем класс с одним методом, в котором будет блок try-catch-finally. Вызов метода также обернем в try-catch.
Все сработает так как и должно:
1.Try
2.F Catch
3.Finally
4.Main catch
Теперь уберем из метода Main блок try-catch и снова запустим программу. На этот раз результат будет немного другой, хотя в обоих случаях exception покидает метод F():
1.Try
2.F Catch
3.Информация об ошибке
4.Finally
В большинстве случаев, необычное с первого взгляда поведение, оказывается вполне объянимым или уже задокументированным. Но, согласитесь, что мало кто досконально читает help перед тем как писать код. Так что желаю вам пореже встречаться с такими сюрпризами.
Пример 1. Меняем местами значения переменных (C#)
С этим поведением я встретился несколько лет назад, когда только начал изучать C#. Применив знакомый метод, чтобы поменять значения 2-х переменных местами, я с удивлением обнаружил, что он не работает.
//Задаем 2 переменные
int x = 1, y = 2;
//Меняем их значения при помощи xor
x ^= y;
y ^= x;
x ^= y;
//Выводим результат [x=2;y=1]
Console.WriteLine("x = {0};y = {1}", x, y);
//Снова меняем их значения, но только пишем все в одну строчку
x ^= y ^= x ^= y;
//Выводим результат [x=0;y=2]
Console.WriteLine("x = {0};y = {1}", x, y);
* This source code was highlighted with Source Code Highlighter.
В итоге, в первый раз все проходит нормально и значения переменных меняются, а во второй раз, вопреки ожиданиям, у нас обнуляется переменная x.
Пример 2. Переводим число в строку (MS SQL)
Вот пример того, как функции cast и convert могут приподносить сюрпризы.
cast(1000 as varchar(3)) --Результатом будет '*'
cast(1000 as nvarchar(3)) --Результатом будет Error
* This source code was highlighted with Source Code Highlighter.
Хотя такое поведение и задокументировано в MSDN, столкнулся я с этим раньше чем прочитал о нем.
Пример 3. Использование NOT IN и IN в условии(MS SQL)
Этот пример также описан в MSDN, но узнал я о таком поведении, только когда из-за него произошла ошибка в программе.
--Создадим тестовую таблицу
create table #tmpTable
(
id int
)
/*Заполним ее числами от 1 до 10*/
--Теперь выполним пару select'ов
select * from #tmpTable where id in (1,2,null,3) --Результат: 3 строки
select * from #tmpTable where id not in (1,2,null,3)--Результат: 0 строк
--Не забудем таблицу удалить
drop table #tmpTable
* This source code was highlighted with Source Code Highlighter.
В отличие от IN, который просто пропускает null, NOT IN всегда возвращает пустую выборку. В общем-то, после небольших размышлений, на тему «почему так?», результат уже не кажется необычным.
Пример 4. Finally и необработанное исключение(C#)
Следующая ситуация мне кажется необычной, потому что меняет поведение в зависимости от того, ловите ли вы исключение или нет.
Итак, напишем класс с одним методом, в котором будет блок try-catch-finally. Вызов метода также обернем в try-catch.
class C
{
public void F()
{
try
{
Console.WriteLine("Try");
throw new Exception("some exception");
}
catch(Exception ex)
{
Console.WriteLine("F Catch");
throw ex;
}
finally
{
Console.WriteLine("Finally");
}
}
}
static void Main(string[] args)
{
try
{
C c = new C();
c.F();
}
catch (Exception)
{
Console.WriteLine("Main catch");
}
}
* This source code was highlighted with Source Code Highlighter.
Все сработает так как и должно:
1.Try
2.F Catch
3.Finally
4.Main catch
Теперь уберем из метода Main блок try-catch и снова запустим программу. На этот раз результат будет немного другой, хотя в обоих случаях exception покидает метод F():
1.Try
2.F Catch
3.Информация об ошибке
4.Finally
Заключение
В большинстве случаев, необычное с первого взгляда поведение, оказывается вполне объянимым или уже задокументированным. Но, согласитесь, что мало кто досконально читает help перед тем как писать код. Так что желаю вам пореже встречаться с такими сюрпризами.