Это очень круто в плане debuggability, позволяет избавиться от необходимости постоянно логировать всякие мелочи, работает прозрачно для существующего и нового кода.
Показать не могу.
Re[12]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, abibok, Вы писали:
A>>Это что-то фирменное. Можно показать?
A>Это очень круто в плане debuggability, позволяет избавиться от необходимости постоянно логировать всякие мелочи, работает прозрачно для существующего и нового кода. A>Показать не могу.
hackability?
Забавно, что в качестве аргумента ты используешь то, что показать не можешь...
Re[13]: Стоит ли переносить инициализацию в отдельный метод?
и думает, что все безопасно, привилегии не уйдут вызывающему. А мы подсунем такой x, который приведет к исключению, и перехватим его до входа в finally, и вернемся в свой код ненадого.
A>Забавно, что в качестве аргумента ты используешь то, что показать не можешь...
В качестве аргумента я описываю реальную задачу, пусть и не очень распространенную (что нормально для всякой достаточно сложной задачи), а вот реализацию показать не могу. Но это не отменяет существование задачи и проблемы.
Re[14]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, abibok, Вы писали:
A>>hackability?
A>В том числе, когда это касается воровства контекста повышенных привилегий. Вызываем мы "некоторый" метод как юзер, а он внутри делает
A>
A>public void Foo(Something x)
A>try
A>{
A> GiveMeAdminPrivileges();
A> Process(x);
A>}
A>finally
A>{
A> RevertToUserPrivileges();
A>}
A>
A>и думает, что все безопасно, привилегии не уйдут вызывающему. А мы подсунем такой x, который приведет к исключению, и перехватим его до входа в finally, и вернемся в свой код ненадого.
Интересно. А если Foo лежит в подписанной сборке в GAC, тоже перехватите? А Code Access Security тоже умеете обходить?
A>>Забавно, что в качестве аргумента ты используешь то, что показать не можешь... A>В качестве аргумента я описываю реальную задачу, пусть и не очень распространенную (что нормально для всякой достаточно сложной задачи), а вот реализацию показать не могу. Но это не отменяет существование задачи и проблемы.
Описание задачи и ее существование не может быть аргументом.
Re[15]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, drol, Вы писали: D>Это верно только для однопоточной ситуации. В многопоточном случае возможны такие "чудеса", как выполнение конструктора параллельно с финализатором.
Чтобы финализатор начал выполняться параллельно с конструктором, нужно, чтобы поток исполнения конструктора дошёл до места, после которого нет обращений к this.
Это означает, что если у нас есть недоинициализированный экземпляр, то ссылка на него удерживается в рутах GC, и в лапы финализатора он не попадёт.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, drol, Вы писали:
D>Кэш данных в архитектурах x86/x64 когерентен. И к обсуждаемым вопросам не имеет никакого отношения.
Не для холивара
Ок, а чем ещё можно объяснить, что пример igor-booch (чуть допилил) не падает?
class Program
{
static Foo foo = new Foo(10000);
static void Main(string[] args)
{
Thread instantiationThread = new Thread(() =>
{
do
{
foo = new Foo(10000);
} while (true);
});
Thread checkInitializedThread = new Thread(() =>
{
do
{
var local = foo;
if (!local._initialized1 | !local._initialized2 | local._val == 0)
{
Console.WriteLine("Bingo!!!");
}
} while (true);
});
instantiationThread.Start();
checkInitializedThread.Start();
Console.ReadKey();
}
class Foo
{
private static readonly Random rnd = new Random(0);
public bool _initialized1;
public bool _initialized2;
public int _val;
public Foo(int count)
{
//Thread.Sleep(10);
_initialized1 = true;
//Thread.Sleep(10);
_initialized2 = true;
_val = rnd.Next(count) + 1;
}
}
}
Здравствуйте, Sinclair, Вы писали:
S>Чтобы финализатор начал выполняться параллельно с конструктором, нужно, чтобы поток исполнения конструктора дошёл до места, после которого нет обращений к this.
Ну да. В чём проблема-то ?
S>Это означает, что если у нас есть недоинициализированный экземпляр, то ссылка на него удерживается в рутах GC, и в лапы финализатора он не попадёт.
Ты как-то узко понимаешь инициализацию. Вот есть поле. Конструктор проставил в него ссылку на объект. А теперь вызывает какие-то методы этого объекта. С этого момента зависимости по this уже нет. Однако инициализация идёт во всю.
Re[15]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, artelk, Вы писали:
A>>и думает, что все безопасно, привилегии не уйдут вызывающему. А мы подсунем такой x, который приведет к исключению, и перехватим его до входа в finally, и вернемся в свой код ненадого. A>Интересно. А если Foo лежит в подписанной сборке в GAC, тоже перехватите? А Code Access Security тоже умеете обходить?
Ну конечно же да. Они же явно пользуются Debugger Services и шаманством с CLR Host, а там all bets are off.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinix, Вы писали:
S>Ок, а чем ещё можно объяснить, что пример igor-booch (чуть допилил) не падает?
Тем, что JIT у CLR очень недалёкий. Видно же в ассемблере, что чтение ссылки из памяти происходит на каждой итерации. Замените потроха checkInitializedThread на более простую конструкцию:
var local = foo;
do
{
} while (local==foo);
Console.WriteLine("local != foo");
...и всё сразу станет по-другому (при запуске Release-сборки вне Visual Studio).
Re[2]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, HowardLovekraft, Вы писали:
HL>Здравствуйте, Аноним, Вы писали:
А>>Есть ли у этого подхода преимущества перед обычной инициализацией через конструктор в C#? HL>Что имеется ввиду? Это: HL>
Re[3]: Стоит ли переносить инициализацию в отдельный метод?
От:
Аноним
Дата:
04.07.13 10:05
Оценка:
Tom>использовать static-методы вида CreateForA(), CreateForB(). Tom>Это до того момента когда вам тесты понадобится писать. В целом для нормально тестируемого кода надо забыть что такое статический метод, или статическая переменная
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, drol, Вы писали: D>>Это верно только для однопоточной ситуации. В многопоточном случае возможны такие "чудеса", как выполнение конструктора параллельно с финализатором. S>Чтобы финализатор начал выполняться параллельно с конструктором, нужно, чтобы поток исполнения конструктора дошёл до места, после которого нет обращений к this. S>Это означает, что если у нас есть недоинициализированный экземпляр, то ссылка на него удерживается в рутах GC, и в лапы финализатора он не попадёт.
Понятно. То есть все будет работать так, как будто финализатор работает после конструктора до тех пор, пока у финализатора не будет какого-нибудь хитрого побочного эффекта, влияющего на наблюдаемое поведение приложения (а не только освобождение занятых системных ресурсов).
Удалось такого добиться на основе глобального изменяемого состояния:
public class A
{
public static int N;
private int x;
public A()
{
N = 42;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(N);
//x = N; //uncomment me
}
~A()
{
N = 666;
}
}
static void Main()
{
new A();
Console.WriteLine("Done...");
Console.ReadKey();
return;
}
В релизе при запуске вне студии выводит 666. Если раскоментировать "x = N;" в последней строке конструктора, то выводит 42.
Здравствуйте, drol, Вы писали:
D>Ты как-то узко понимаешь инициализацию.
Вот есть поле. Конструктор проставил в него ссылку на объект. А теперь вызывает какие-то методы этого объекта. С этого момента зависимости по this уже нет. Однако инициализация идёт во всю.
Инициализация — это, по определению, изменение состояния объекта. Как только мы перестали менять состояние объекта — его инициализация завершилась.
Если финализатор объекта рассчитывает на какое-то определённое состояние другого объекта — это вина финализатора.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Стоит ли переносить инициализацию в отдельный метод?
Здравствуйте, Tom, Вы писали:
Tom>Это до того момента когда вам тесты понадобится писать. В целом для нормально тестируемого кода надо забыть что такое статический метод, или статическая переменная
Ну, без фанатизма.
В данном случае, статический метод ничем не отличается от конструктора. Если у тебя код организован так, что экземпляр этого класса ты инжектишь, а не создаешь прямо в том классе, который хочешь оттестировать, то совершенно пофиг как ты его создаешь в боевом коде, через статический метод или честный конструктор, на тестировании это никак не скажется.