Источник
Вопрос 1
Есть следующие объявления классов A и B:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class A { virtual void Foo() // << virtual or abstract members cannot be private { Console.WriteLine("Class A"); } } class B: A { override void Foo() // << no sutable method found to override { Console.WriteLine("Class B"); } } |
Что выведут на консоль такие вызовы метода Foo()
:
1 2 3 4 5 6 7 8 |
B obj1 = new A(); obj1.Foo(); B obj2 = new B(); obj2.Foo(); A obj3 = new B(); obj3.Foo(); |
Ответ
Ошибка компиляции. Методы Foo надо сделать с модификатором public. Причем оба метода с одинаковым модификатором.
1 2 3 |
Error CS0621 'Program.A.Foo()': virtual or abstract members cannot be private Syntax C:\C#\Syntax\Syntax\Syntax\Program.cs 27 Active Error CS0621 'Program.B.Foo()': virtual or abstract members cannot be private Syntax C:\C#\Syntax\Syntax\Syntax\Program.cs 34 Active Error CS0115 'Program.B.Foo()': no suitable method found to override Syntax C:\C#\Syntax\Syntax\Syntax\Program.cs 34 Active |
Теперь изменим немного код. Добавим модификатор public методам Foo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class A { public virtual void Foo() { Console.WriteLine("Class A"); } } class B : A { public override void Foo() { Console.WriteLine("Class B"); } } |
Попробуем завести программу
1 2 3 4 5 6 7 8 9 |
// B obj1 = new A(); // << Error CS0266 Cannot implicitly convert type 'Syntax.Program.A' to 'Syntax.Program.B'.An explicit conversion exists (are you missing a cast?) Syntax C:\C#\Syntax\Syntax\Syntax\Program.cs // obj1.Foo(); B obj2 = new B(); obj2.Foo(); // << class B A obj3 = new B(); obj3.Foo(); // class B Console.ReadLine(); |
В данном случае мы потомку пытались присвоить экземпляр предка. Ошибка конвертации типов.
1 |
B obj1 = new A(); |
И даже, если мы сделаем так
1 |
B obj1 = (B)new A(); |
Мы все равно не приведем типы. Получим
1 |
System.InvalidCastException: 'Не удалось привести тип объекта "A" к типу "B".' |
Итого на консоли у нас получится, если закомментируем первый случай
1 2 |
Class B Class B |
Вопрос 2
Есть следующая структура:
1 2 3 4 5 6 7 8 9 10 11 12 |
public struct S : IDisposable { private bool dispose; public void Dispose() { dispose = true; } public bool GetDispose() { return dispose; } } |
Что будет выведено в следующем случае:
1 2 3 4 5 6 |
var s = new S(); using (s) { Console.WriteLine(s.GetDispose()); } Console.WriteLine(s.GetDispose()); |
Ответ
Интересный пример. Using работает так, что если объект поддерживает интерфейс IDisposable, то по завершении использования автоматически включается имплементация IDisposable.
Эквивалентом было бы
1 2 3 4 5 6 7 |
SomeDisposableType t = new SomeDisposableType(); try { OperateOnType(t); } finally { t.Dispose(); } |
Но using короче и элегантнее
1 2 3 |
using (SomeDisposableType u = new SomeDisposableType()) { OperateOnType(u); } |
Вернемся к нашему случаю. По идее, у нас должно было произойти переключение с false на true в момент окончания инструкции using. И это происходит. То есть мы попадаем в имплементацию интерфейса IDisposable. На консоли у нас следующее
1 2 3 |
False Disposing... False |
Но!
Ключевым моментом здесь является то, что мы используем структуру, а не класс. Получается у нас 2 объекта. И Dispose вызывается для одного из них.
1 2 3 |
... using (s) ... |
Вопрос 3
Есть код
1 2 3 4 5 6 7 8 9 |
List<Action> actions = new List<Action>(); for(var count=0; count<10; count++) { actions.Add(() => Console.WriteLine(count)); } foreach(var action in actions) { action(); } |
Что будет выведено на консоль? Варианты ответов:
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
- Код сгенерирует исключение
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Ответ
10, 10, 10, 10, 10, 10, 10, 10, 10, 10
Подробный разбор ответа на хабре
Вопрос 4
Что будет в консоли?
1 2 3 4 5 6 |
int i = 1; object obj = i; ++i; Console.WriteLine(i); Console.WriteLine(obj); Console.WriteLine((short)obj); |