Здравствуйте, IT, Вы писали:
MA>>Ты точно в релизе проверяешь? MA>>Потому что в дебаге все они живут до конца метода. IT>Т.е. есть ньюансы?
Я про релиз написал сразу. И вообще харош прикалываться, ты ж сам всё отлично знаешь как это работает.
Здравствуйте, StandAlone, Вы писали: SA>Заборов нет, но у hr есть техпроцесс обработки кандидата, за исполнение которого ей платят. И она сделает все от нее зависящее, чтобы прогнать единицу хьюмен ресурс по всем этапам. SA>Силой нет, а в единую базу неблагополучных кандидатов добавить как за здрасте. Информация, если что, от первой, так сказать, морды.
Ох, ну я не знаю, сделайте грустное лицо, скажите "что-то я подзабыл, давайте я лучше подготовлюсь и как-нибудь в другой раз приду". Если явно не конфронтировать, какой смысл им заносить Вас в какие-то базы?
Здравствуйте, StandAlone, Вы писали:
SA>Здравствуйте, ylp, Вы писали:
ylp>>Если да, то начиная со скольки лет опыта необязательно знать, зачем нужен цикл while?
SA>А Вы помните семантику оператора JNZ?
(телепат mode on)
Если вы про x86 ассемблер
jump if not zero, делать jump если zero bit flag is not set. И это при том, что на ассемблере я писал последний раз 10 лет назад.
SA>В каком регистре должен быть операнд условной адресации в модели памяти small?
Вопрос сформулирован недостаточно точно, требуется больше контекста, даже моих телепатских способностей не хватает
\S>С того момента, как получаешь уровень "good team player"
имхо, человек все-таки имел в виду что-то другое. Хотелось бы услышать начальника транспортного цеха
Здравствуйте, Mishka, Вы писали:
M>Итак, Лондон, большой банк, всё серьёзно. Встречаю соискательницу с чётким CV, 9 лет опыта С#, WPF, сервер, в общем на бумаге всё что надо. M>Вопрос: using в С# где и зачем M>Ответ:
Шарпа не знаю, для общего развития погуглил — это оно? Насколько вообще принято на шарпе писать без исключений, или это как ява где без них никуда?
Здравствуйте, aik, Вы писали:
M>>Итак, Лондон, большой банк, всё серьёзно. Встречаю соискательницу с чётким CV, 9 лет опыта С#, WPF, сервер, в общем на бумаге всё что надо. M>>Вопрос: using в С# где и зачем M>>Ответ: aik>Шарпа не знаю, для общего развития погуглил — это оно?
Да. На Java аналогом является try-with-resources. На Python — with. Всё это обрезанные аналоги "RAII" из C++.
Здравствуйте, Mishka, Вы писали:
M>Итак, Лондон, большой банк, всё серьёзно. Встречаю соискательницу с чётким CV, 9 лет опыта С#, WPF, сервер, в общем на бумаге всё что надо. M>Вопрос: using в С# где и зачем M>Ответ: M>
M>using
M>{
M> var o = new Object();
M>}
M>// здесь GC будет знать что объект свободен и его можно убрать
M>
M>
Посылайте на хакерранк. Вопрос про синтаксис- ну, какой-то на дебилоидов рассчитанный. Может тетя писала под началом архитекта-самодура, и using не использовался, писали по "coding guidelines" 20 летней давности. Тетя сымпровизировпла неудачно.
Здравствуйте, fmiracle, Вы писали:
F>Это все из реального опыта виденного в работе. На удивление часто люди не знают не очень-то понимают для чего нужен Dispose или Close у файлов, соединений с БД и подобного.
Вся работа с коннекшенами, close и т.д у вменяемых людей сосредоточена в либах. Когда ты работаешь с файлом, ты используешь библиотечную функцию readFile, которое возвращает тебе содержимое. Или итератор. То есть ты обратился у либе, получил итератор, и ни о каких пулах не думаешь. Если ты в состоянии так написать код — ты сеньер. Если для того, чтобы прочитать контент ты каждый раз копипастишь код открытия файла, чтения, внутрь добавляешь логику, оборачиваешь это в try catch и потом обязательно закрываешь, и так 1000 раз в проекте — ты очень фиговый джуниор.
Как ты сделаешь в либах, чтобы не копипастить — дело десятое. Хоть поток стартуй отдельный, который отслеживает обращения по итератору и если обращений не было давно — закрывает соединение. А если потом снова начали у итератора данные запрашивать через длительный промежуток времени — переоткрывает. Или просто передаешь лямбду, которая для каждой строчки файла выполняет определенную логику. В результате у тебя во всех проектах твоей компании будет одна либа, где есть вот такое явное открытие и закрытие. А в высокоуровневом коде, который чаще всего и пишется — никакого явного управления ресурсами, минимум строчек кода и все по делу. Если смогли так сделать — значит у вас культура кодирования на высоком уровне. Если же у вас весь проект сплошной try catch using и т.д, включая бизнес логику, и те места, где можно забыть что то и допустить ошибку — извиняйте, но у вас крайне низкая культура кодирования.
Здравствуйте, Michael7, Вы писали:
M>Тут я пас, MSIL еще не изучал. В принципе, логично просто счетчик ссылок уменьшить до нуля после выхода из блока, а зачищать лишь при необходимости или по расписанию.
Счетчик ссылок актуален для C++ smart-pointers и для COM объектов.
Сборка мусора в .NET — работает по совсем другому принцыпу:
Здравствуйте, IT, Вы писали: IT>Будет ли разным генерируемый код для следующего? IT>
IT>void Foo()
IT>{
IT> {
IT> object o = new object();
IT> }
IT>}
IT>void Foo()
IT>{
IT> object o = new object();
IT> {
IT> }
IT>}
IT>void Foo()
IT>{
IT> object o;
IT> {
IT> o = new object();
IT> }
IT>}
IT>
IT>Я не уверен.
Если проверить поведение экспериментально, то видно, что в релиз-сборке, объект, на который ссылается переменная, может быть собран сборщиком мусора после того, как переменная уже не используется. Неважно, внутри блока или нет. Если переменная объявлена внутри блока, то это просто точная уверенность, что дальше она уже не используется.
вот такой пример на коленке
class Tst
{
public string Name { get; set; }
public Tst(string name)
{
Name = name;
}
~Tst()
{
Console.WriteLine( $"finalizer called for {Name}" );
}
public override string ToString()
{
return Name;
}
}
static void Main( string[] args )
{
object o1;
var o2 = new Tst("o2");
var o4 = new Tst( "o4" );
{
var o3 = new Tst("o3");
o1 = new Tst("o1");
}
Console.WriteLine( "init done" );
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine( "method almost complete" );
Console.WriteLine( "last use of {0}", o4 );
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine( "method complete" );
}
вывод в Релизе:
init done
finalizer called for o1
finalizer called for o3
finalizer called for o2
method almost complete
last use of o4
finalizer called for o4
method complete
Т.е. первые 3 объекта успешно собираются сборщиком мусора еще до окончания метода. И при этом неважно, как они объявлены — значение имеет лишь, что на момент сборки мусора CLR видит, что далее эти переменные не используются.
В дебаге, кстати, вывод другой, там никакие локальные объекты не собираются до окончания метода:
init done
method almost complete
last use of o4
method complete
finalizer called for o1
finalizer called for o3
finalizer called for o4
finalizer called for o2
Здравствуйте, aik, Вы писали:
aik>Здравствуйте, Mishka, Вы писали:
M>>Итак, Лондон, большой банк, всё серьёзно. Встречаю соискательницу с чётким CV, 9 лет опыта С#, WPF, сервер, в общем на бумаге всё что надо. M>>Вопрос: using в С# где и зачем M>>Ответ:
aik>Шарпа не знаю, для общего развития погуглил — это оно? Насколько вообще принято на шарпе писать без исключений, или это как ява где без них никуда?
using в С# используется в 3-ёх различных ситуациях. Dispose популярен поскольку на всех интервью его спрашивают. 2-ой — using System тот же Java import (daaah!), а вот 3-ий — это для тех кто реально клювом не щёлкает.
M>Итак, Лондон, большой банк, всё серьёзно. Встречаю соискательницу с чётким CV, 9 лет опыта С#, WPF, сервер, в общем на бумаге всё что надо. M>Вопрос: using в С# где и зачем M>Ответ: M>
M>using
M>{
M> var o = new Object();
M>}
M>// здесь GC будет знать что объект свободен и его можно убрать
M>
M>
Я тут один такой идиот который НЕ понимает зачем задавать на собеседовании вопрос указывая не корректный, не компилирующийся код?
Здравствуйте, IT, Вы писали:
IT>Если указатель в стеке не обнулить или не переиспользовать, то висящий на нём объект будет болтаться в GC до выхода из метода. Вот я и спрашиваю, что там происходит.
Зависит от:
а) режима компиляции Debug/Release. В Debug гарантированно будет.
б) В Release чаще нет, то есть даже так — я не встречал ситуаций когда указатель на объект живет дольше, чем его последнее использование, но допускаю, что возможны случаи, что GC будет считать его достяжимым до конца метода.
В простейшем случае не зависит от скобок никак, тесты:
[TestFixture]
public class VisibilityTests
{
[Test]
public void InBracketsTest()
{
{
var foo = new Foo();
foo.Baz();
}
dotMemory.Check(m => { Assert.AreEqual(0, m.GetObjects(set => set.Type.Is<Foo>()).ObjectsCount); });
}
[Test]
public void NoBracketsTest()
{
var foo = new Foo();
foo.Baz();
dotMemory.Check(m => { Assert.AreEqual(0, m.GetObjects(set => set.Type.Is<Foo>()).ObjectsCount); });
}
}
Вообще говоря правильный вопрос — будет ли GC считать объект достяжимым? В рассматриваемом случае ответ — нет.
Здравствуйте, IT, Вы писали: MA>> Всё правильно. При этом GC умеет сопостовлять IP (instruction pointer, полагаю offset внутри метода) с тем, что считать живым на стэке. Поэтому зануливаний ему и не нужно. IT>Это элементарно проверить. IT>Никто ничего не сопоставляет. Я бы сильно удивился если бы это было так.
Ещё раз что бы развеять этот вопрос.
source
class MyClass
{
~MyClass()
{
Console.WriteLine("~MyClass");
}
public void Hello(int a, int b)
{
Console.WriteLine("Hello!");
}
}
class Program
{
static void Main(string[] args)
{
// Debugger.Launch();var o = new MyClass();
// Этот тупой способ для того что бы переменная o оказалась на стэке
// Иначе она останется только в регистреfor (var i = 0; i < 100; i++)
{
var a = i * 3;
var b = i + a * 4;
Console.WriteLine("Hello: {0} {1}", a, b, i * 2, a + i);
}
o.Hello(1, 2);
Console.WriteLine("---- GC #1");
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine("---- GC #2");
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine("---- About exit");
}
Результат будет различаться в зависимости от:
— Скомпилировав в Release (и запускаем без отладчика, CTRL+F5 в студии). Можно и под отладчиком, но тогда нужно включить Suppress JIT optimizations on module load.
---- GC #1
~MyClass
---- GC #2
---- About exit
— Скомпилировав в Debug (и запускаем без отладчика, CTRL+F5 в студии)
---- GC #1
---- GC #2
---- About exit
~MyClass
asm (x86)
--- H:\!temp\ConsoleApplication18\ConsoleApplication18\Program.cs --------------
27: Debugger.Launch();
009F044A EC in al,dx
009F044B 57 push edi
009F044C 56 push esi
009F044D 53 push ebx
009F044E 83 EC 08 sub esp,8
009F0451 E8 AA 05 B7 71 call 72560A00
28: var o = new MyClass();
009F0456 B9 A0 4D 70 00 mov ecx,704DA0h
28: var o = new MyClass();
009F045B E8 F0 76 6A 72 call 73097B50
009F0460 89 45 EC mov dword ptr [ebp-14h],eax ; сохранили в стэке o.
; Далее по листингу в этом методе никто [ebp-14h] зануливать не будет
; Однако он будет собран уже на первом вызове GC.
; Аналогично для случая с регистрами.
29:
30: for (var i = 0; i < 100; i++)
009F0463 33 FF xor edi,edi
31: {
32: var a = i * 3;
009F0465 8D 1C 7F lea ebx,[edi+edi*2]
33: var b = i + a * 4;
009F0468 8D 04 9F lea eax,[edi+ebx*4]
009F046B 89 45 F0 mov dword ptr [ebp-10h],eax
34: Console.WriteLine("Hello: {0} {1}", a, b, i * 2, a + i);
009F046E B9 B6 41 A2 71 mov ecx,71A241B6h
009F0473 BA 04 00 00 00 mov edx,4
009F0478 E8 33 2D D0 FF call 006F31B0
009F047D 8B F0 mov esi,eax
009F047F B9 80 8D F1 71 mov ecx,71F18D80h
009F0484 E8 3F 2C D0 FF call 006F30C8
009F0489 89 58 04 mov dword ptr [eax+4],ebx
009F048C 50 push eax
009F048D 8B CE mov ecx,esi
009F048F 33 D2 xor edx,edx
009F0491 E8 DA 74 6A 72 call 73097970
009F0496 B9 80 8D F1 71 mov ecx,71F18D80h
009F049B E8 28 2C D0 FF call 006F30C8
009F04A0 8B D0 mov edx,eax
009F04A2 8B 45 F0 mov eax,dword ptr [ebp-10h]
009F04A5 89 42 04 mov dword ptr [edx+4],eax
009F04A8 52 push edx
009F04A9 8B CE mov ecx,esi
009F04AB BA 01 00 00 00 mov edx,1
009F04B0 E8 BB 74 6A 72 call 73097970
009F04B5 B9 80 8D F1 71 mov ecx,71F18D80h
009F04BA E8 09 2C D0 FF call 006F30C8
009F04BF 8B D0 mov edx,eax
34: Console.WriteLine("Hello: {0} {1}", a, b, i * 2, a + i);
009F04C1 8B C7 mov eax,edi
009F04C3 03 C0 add eax,eax
009F04C5 89 42 04 mov dword ptr [edx+4],eax
009F04C8 52 push edx
009F04C9 8B CE mov ecx,esi
009F04CB BA 02 00 00 00 mov edx,2
009F04D0 E8 9B 74 6A 72 call 73097970
009F04D5 B9 80 8D F1 71 mov ecx,71F18D80h
009F04DA E8 E9 2B D0 FF call 006F30C8
009F04DF 03 DF add ebx,edi
009F04E1 89 58 04 mov dword ptr [eax+4],ebx
009F04E4 50 push eax
009F04E5 8B CE mov ecx,esi
009F04E7 BA 03 00 00 00 mov edx,3
009F04EC E8 7F 74 6A 72 call 73097970
009F04F1 8B 0D BC 22 53 03 mov ecx,dword ptr ds:[35322BCh]
009F04F7 8B D6 mov edx,esi
009F04F9 E8 12 2A B7 71 call 72562F10
30: for (var i = 0; i < 100; i++)
009F04FE 47 inc edi
009F04FF 83 FF 64 cmp edi,64h
009F0502 0F 8C 5D FF FF FF jl 009F0465
35: }
36: o.Hello(1, 2);
009F0508 6A 02 push 2
009F050A 8B 4D EC mov ecx,dword ptr [ebp-14h]
009F050D BA 01 00 00 00 mov edx,1
009F0512 FF 15 88 4D 70 00 call dword ptr ds:[704D88h]
37:
38: Console.WriteLine("---- GC #1");
009F0518 8B 0D C0 22 53 03 mov ecx,dword ptr ds:[35322C0h]
009F051E E8 E1 4C 3D 71 call 71DC5204
009F0523 E8 18 47 6D 72 call 730C4C40
009F0528 8B C8 mov ecx,eax
009F052A 6A 01 push 1
009F052C 6A 00 push 0
009F052E BA 01 00 00 00 mov edx,1
009F0533 E8 E0 16 AC 71 call 724B1C18
40: GC.WaitForPendingFinalizers();
009F0538 E8 DF 78 34 71 call 71D37E1C
41: Console.WriteLine("---- GC #2");
009F053D 8B 0D C4 22 53 03 mov ecx,dword ptr ds:[35322C4h]
009F0543 E8 BC 4C 3D 71 call 71DC5204
009F0548 E8 F3 46 6D 72 call 730C4C40
009F054D 8B C8 mov ecx,eax
009F054F 6A 01 push 1
009F0551 6A 00 push 0
009F0553 BA 01 00 00 00 mov edx,1
009F0558 E8 BB 16 AC 71 call 724B1C18
43: GC.WaitForPendingFinalizers();
009F055D E8 BA 78 34 71 call 71D37E1C
44: Console.WriteLine("---- About exit");
009F0562 8B 0D C8 22 53 03 mov ecx,dword ptr ds:[35322C8h]
009F0568 E8 97 4C 3D 71 call 71DC5204
009F056D 8D 65 F4 lea esp,[ebp-0Ch]
009F0570 5B pop ebx
009F0571 5E pop esi
009F0572 5F pop edi
009F0573 5D pop ebp
009F0574 C3 ret
Здравствуйте, fmiracle, Вы писали:
F>Я не собеседую в Лондоне в большой банк, а только в РФ в небольшую компанию. И я часто спрашиваю что такое метод Dispose, для чего применяется, и уже не раз получал ответ, что он нужен для того, чтобы сборщик мусора теперь мог собрать этот объект F>При этом человек может работать с C# уже несколько лет, в т.ч. с базами данных.
У меня был такой случай. Чел с очень приличным по годам опытом.
Вопрос: "Расскажите, что такое финализатор".
Ответ: "Знаю только, что его лучше не вызывать".
Наверное, дальше мне стоило спросить, как его вызвать.
Здравствуйте, Mishka, Вы писали:
M>Здравствуйте, sharpcoder, Вы писали:
S>>Прикинь, она идеально знает алгоритмы, структуры данных, паттерны, машинленинг и т.п. S>>и при этом сама unig не использует, предпочитая вручную вызывать Dispose()?
M>Это единственное где using используется?
Ну удиви меня, скажи что делает еще using() кроме гарантированного вызова Dispose()?
А то я 10 лет не кодирую, может он научился еще что-то делать?
Здравствуйте, MxMsk, Вы писали:
MM>Вопрос: "Расскажите, что такое финализатор". MM>Ответ: "Знаю только, что его лучше не вызывать". MM>Наверное, дальше мне стоило спросить, как его вызвать.
Ну как-как...
GC.Collect();
GC.WaitForPendingFinalizers();
Так что всё верно сказал, обычно его лучше не вызывать.
А если серьёзно, то это довольно глупый вопрос, чисто "на широту взглядов". Знает — хорошо, не знает... тоже ничего страшного, штука ведь довольно редкая.