singlepost

Интересные примеры по C# (для самообразования) << На главную или назад  

Ищу интересные нетривиальные примеры для самообразования.
Нашел интересный пример в книге Эндрю Троелсена Язык программирования С# 2005. Кому интересно, не запуская приложение определить, что выведется в конце.

public class A
{
public int p;
public A(int x)
{
p = x;
}
}

public static void SendA(A a)
{
a.p = 50;
a = new A(11);
}

static int Main()
{
A a = new A(10);
SendA(a);
Console.WriteLine(a.p);
Console.ReadKey();
return 0;
}

Кто знает интересные примеры, прошу выкладывать здесь.

69 ответов в теме “Интересные примеры по C# (для самообразования)”

  1. 20
    Жека Кирпичев ответил:

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

  2. 19
    Алексей Тимофеев ответил:

    Передай параметр "а" по ссылке… явно указав что передается по ссылке (ref) и увидишь разницу…
    А типы данных, что ссылочные, что "примитивные" все это объекты, и в любом случае мы используем ссылки на них. Другое дело типы по значению могут являться базовыми для которых четко определена операция "=". И еще разница в том где под них память выделяется.

    И я бы не стал сильно верить wikipedia, я с уважением отношусь к этому сайту, но все же… "This article's citation style may be unclear. The references used may be made clearer with a different or consistent style of citation, footnoting, or external linking."…

  3. 18
    Жека Кирпичев ответил:

    Приведенная статья использует не общепринятую терминологию, а книжка у меня не открывается.
    Вот общепринятая: //en.wikipedia.org/wiki/Evaluation_strategy

    Передача по значению – call by value.
    При этом значение аргумента копируется, и функция не может изменить значение в контексте вызывающего.

    Передача по ссылке – call by reference.
    При этом передается не копия значения аргумента, а ссылка на него, и функция может, изменив его, повлиять на значение, видимое вызывающим.

    В C#, очевидно, для значений ссылочных типов используется второе, поскольку при передаче значений ссылочного типа функции НЕ осуществляется копирование этого объекта, а передается его адрес, т.е. ссылка на него.

    C# также поддерживает передачу по "ссылке на ссылку" с помощью ключевого слова ref – при этом передается ссылка на область памяти, содержащую *адрес* значения (в случае ссылочного типа это адрес объекта, в случае примитивного типа – само значение).

    То же самое написано в приведенной тобою статье, но другими словами – в ней значением переменной ссылочного типа называется адрес объекта, на который она указывает, а не сам объект. Это неудачный выбор терминологии с их стороны, т.к. он не согласуется с общепринятым и стирает разницу между двумя принципиально разными типами передачи параметров.

  4. 17
    Алексей Тимофеев ответил:

    Ув. Жека jkff Кирпичев я никак не хотел Вас обидеть и не сомневаюсь в Ваших знаниях, но писать, такое:
    > C# все параметры ссылочных типов (т.е. все кроме примитивных типов и >структур, насколько я помню) передаются по ссылке
    Согласитесь, что для C# это не верно!!!… Пусть примитивный тип это как я понимаю "Базовый тип характеризуемый значением", возможно это просто разная лексика. НО почему передаются по ссылке???? В С# по-умолчанию передается по значению (Если по ссылке то это явно указывается, это же основы).
    А по поводу "=" у меня конечно даже слов уже нет…
    //msdn.microsoft.com/ru-ru/library/s6938f28.aspx
    //books.google.com.ua/books?id=_Er0X0kBAYIC&amp...
    Так что пробелы оказывается тоже есть….

    P.S. В последнем примере ответ "01234", НО если закрыть верхний try…

  5. 16
    Жека Кирпичев ответил:

    По-моему, 01234 будет; кажется, никакого подвоха нет.

  6. 15
    Людмила Уланова ответил:

    Народ, подобных примеров, по-моему, достаточно много.. В каждом тесте они встречаются, "что будет на экране, если <много кода>". Кому интересно, загуглите тесты по C#.. =)

  7. 14
    Михаил Семионенко ответил:

    Есть еще пример…
    try
    {
    try
    {
    throw new Exception();
    }
    catch (Exception ex)
    {
    try
    {
    Console.Write("0");
    throw new Exception();;
    }
    catch
    {
    Console.Write("1");
    throw;
    }
    finally
    {
    Console.Write("2");
    }
    }
    catch
    {
    Console.Write("3");
    }
    finally
    {
    Console.Write("4");
    }

  8. 13
    Михаил Семионенко ответил:

    Ты знаешь, я этот вопрос ряду программистов матерых задал, и почти все ответили 11 =)

  9. 12
    Михаил Семионенко ответил:

    Чувствую интересный пример я нашел)

  10. 11
    Жека Кирпичев ответил:

    Да нет, вообще-то, пример тривиальнее некуда :) Просто он вскрыл пробелы в ряде базовых областей знания у ряда комментаторов :)

  11. 10
    Михаил Митрофанов ответил:

    to Алексей Тимофеев
    Да, кстати, если уж на то пошло. то в C# вообще нету ссылок на области памяти, а есть идентификаторы объектов, по которым дальше и идет связывание.
    Так что если Вы пытаетесь писать правильно, то и пишите не "копия адреса ссылки", а "копия идентификатора объекта, ссылающегося на область памяти"

  12. 9
    Жека Кирпичев ответил:

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

  13. 8
    Тимур Багаутдинов ответил:

    to Алексей Тимофеев
    Шел бы ты сам учить ООП…

    >> (а не ссылка на этот адрес, не забываем что процедура static)
    ээ, т.е. если процедура static то передается не ссылка на адрес? бред!

    убираю static
    A a = new A(10);
    a,SendA(a);
    и тоже самое…

    >>понятие "примитивный тип" вообще не понимаю
    читай книжки… умные.. к примеру Рихтера того же
    primitive types – типы, которые поддерживаются компилятором напрямую

    >> 2. (Операция "=" в C# не перегружена и запись "a = b" означает "связать имя a со значением b") – где такое написано???????? = – это присвоение!!!
    Фразы из контекста дергать – явно не красиво.. читай дальше внимательнее

  14. 7
    Алексей Тимофеев ответил:

    Все очень просто и ничего здесь странного….

    1. Первоначально в Main создается объект класса "А" и записывается в переменную "а" (которая является ссылкой, т.е. АДРЕСОМ на экземпляр объекта), в этом экземпляре указывается опять-таки адрес на то место где хранится значение переменной "р" (т.к. все объекты ссылочные). Таким образом получили значение 10 при создании объекта.
    2. При вызове процедуры SendA ей передается КОПИЯ АДРЕСА на наш объект (а не ссылка на этот адрес, не забываем что процедура static), естественно, что при ссылке через этот адрес к объекту "р" можно изменить его значение (р=50).
    3. Далее создаем новый экземпляр объекта (ВТОРОЙ), который естественно записывает значение р=11, НО АДРЕС ЭТОГО ЭКЗЕМПЛЯРА ЗАПИСЫВАЕТСЯ ВКОПИЮ (и дальнейшие изменения переменной "р" не приведут к изменению переменной "р" созданной в Main, т.к. ссылку на ТОТ объект мы уже перезаписали и по сути работаем с другим экземпляром объекта). Таким образом при выводе переменной "р" получаем 50.

    Нужно учить основы ООП ))))

    P.S. Если бы такое писать на С/С++ и классы занимали бы достаточно памяти, и если процедура вызывалась бы достаточно часто то создавалась бы утечка памяти, что есть плохо…. да и в шарпе такой код создает дополнительную путаницу…

    А так пример познавательный, типа "Так плохо делать…." )))

    #3
    в первой то строке обращаемся к нашему объекту хоть и к копии, т.к. это копия адреса ссылки.

    #4
    не понятно, что такое состояние?!?!?… а.р=50 т.е.адрес(а).адрес(р)=50

    #5
    в C# нет понятия "*a", так как объект и так ссылка и вообще все объекты это ссылки

    #7
    1. понятие "примитивный тип" вообще не понимаю, т.е. если есть где-то значение 50 записанное в переменной "р" – то "р" это сслыка на этот кусок памяти где 50 записано. Используя эту ссылку может изменить это значение (посредством фреймворк)))) )
    2.(Операция "=" в C# не перегружена и запись "a = b" означает "связать имя a со значением b") – где такое написано????????= – это присвоение!!!
    3.(имя формального параметра..) – что за лексика????? мы о программировании говорим никаких формальных параметров!!!!!!!! все очень конкретно

  15. 6
    Жека Кирпичев ответил:

    В C# все параметры ссылочных типов (т.е. все кроме примитивных типов и структур, насколько я помню) передаются по ссылке.
    Операция "=" в C# не перегружена и запись "a = b" означает "связать имя a со значением b", а не "перезаписать содержимое объекта, с которым связано имя a, значением b".
    Поэтому "a = new A(11)" лишь связывает, в контексте процедуры sendA, имя формального параметра "a" со значением "new A(11)", что никак не изменяет значение переданного фактического параметра, и не изменяет то, с каким значением связан идентификатор a в главной процедуре.

  16. 5
    Виктор Аникин ответил:

    Действительно, ответ 50. А почему он перезаписывает 10, ведь вроде не по ссылке передаем, и почему не 11?

  17. 4
    Димон Дренкалюк ответил:

    чё-то я не пойму, мож тупой.. В строке "A a = new A(10);" не должно быть случайно " *а " вместо "а" ? оО

  18. 3
    Тимур Багаутдинов ответил:

    Ну так да… 11 он его и не сделает…
    а a.p = 50; меняет состояние объекта, а не адрес ссылки

  19. 2
    Дмитрий Коковцев ответил:

    2Тимур
    Параметр в функцию SendA передается не по ссылке, поэтому функция не может его изменить. Следовательно, программа выдаст 10
    Хотя, возможно, я ошибаюсь

  20. 1
    Тимур Багаутдинов ответил:

    Да 50 должен…
    Ну всякие тонкости и у Рихтера можно посмотреть

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.