Zainspirowany tematem java zaawansowane interview questions
Czy znacie jakieś dziwne/ciekawe/wtf/zaawansowane (ponad poziom seniora) rzeczy w C#?
Zainspirowany tematem java zaawansowane interview questions
Czy znacie jakieś dziwne/ciekawe/wtf/zaawansowane (ponad poziom seniora) rzeczy w C#?
na dobra sprawe takie jak w javie :)
ja czesto prosilam o zaimplementowanie czegos identycznego wydajnosciowo do List<T> ale z gwarancja nie uzywania LOH (tj bez fragmentowania pamieci) albo cos co wymaga message loop czy innych windowsowych bebechow. mozna pogadac o implikacjach zwiazanych z interop jak finalizatory, pinning, memory alignment itp
Dużo jest takich pytań. Np. Jaka wersja JIT, będzie optymalna dla urządzeń mobilnych?. W jakim miejscu jest alokowana pamięć dla klas statycznych. Ludzie wykładają się nawet na takich podstawach jak pytaniach o algorytm, jakiego używa sort w linq.
Używając tylko System;
Napisz funkcję (jedną) z jednym przeciążeniem, która przyjmie różną ilość argumentów różnego typu i je wyświetli
Bez tworzenia żadnych własnych kolekcji, class lub object[] List<object> itd, bez deklarowania zmiennych, bez użycia new. Bez tego wszystkiego do wrzucenia danych
do funkcji. Oczywiście również bez traktowania argsów jako napis
Przykładowe dane
5,"x", 5.0, 15
"test", 'b', 5, -2, 5, 199.3m, 3, 3.0, 4.0, -12, 'q'
static void Main(string[] args)
{
int number;
string text;
decimal number2;
ReturnSomething(out number, out text, out number2);
Console.WriteLine($"{number} {text} {number2}");
Console.ReadKey();
}
public static void ReturnSomething(int number, string text, decimal number2)
{
}
public static void ReturnSomething(out int number, out string text, out decimal number2)
{
number = 55;
text = "text";
number2 = 5.5m;
}
Ja bym zadanie z przeciazeniem zrobi tak:
static void Main(string[] args)
{
Test((() => Test(1,1, "dwa", 2.2, 2M)));
Console.ReadKey();
}
public static void Test(Action action)
{
action.Invoke();
}
public static void Test(params dynamic[] args)
{
foreach(var item in args)
{
Console.WriteLine(item);
}
}
A może coś w rodzaju curryingu :)
static void Main(string[] args)
{
Bar(5)("x")(5.0)(15);
}
delegate Foo Foo(object item);
static Foo Bar(object item)
{
Console.Write(item);
return x =>
{
Console.Write(", ");
return Bar(x);
};
}
Chodziło mi o __arglist
public static void Main(string[] args)
{
Foo(__arglist(1, 'q', 2.0,"zzz"));
Foo(__arglist('o', -15, "?^", 6, -1, "test"));
}
static void Foo(__arglist)
{
ArgIterator iter = new ArgIterator(__arglist);
for (int n = iter.GetRemainingCount(); n > 0; n--)
{
Console.WriteLine(TypedReference.ToObject(iter.GetNextArg()));
}
}
Przychodzą mi do głowy tylko, błędy pamięci albo zewnętrzne środowiska uruchomieniowego, ale w takim momencie powinieneś zakończyć działanie aplikacji, zamiast używać finally. Może masz na myśli jakieś dodatkowe zabezpieczenie nisko poziomowe, nie wiem...
Wiele osób może też nie wiedzieć o tym, że member może być np. private protected
czy protected internal
.
private protected
to słabo udana próba naprawy protected internal
(powinno być tak od początku), a protected internal
to nieprzydatny dziwoląg.
Proszę wymienić najczęstszą sytuację, która wymaga przeciążenia operatorów "== oraz !=". Po czym omówić problemy bezpieczeństwa oraz wydajnościowe związane z tą sytuacją. ;)
Proszę wymienić najczęstszą sytuację, która wymaga przeciążenia operatorów "== oraz !="
Robię sobie klasę do obsługi liczb zespolonych i oprócz arytmetyki, którą chcę mieć na operatorach, przeciążam także porównanie, co by mi było prościej na tych liczbach operować. Przykład nawet częsty na studiach. Z tego co się orientuję oba te operatory muszą być przeciążone. Nie można przeciążyć tylko jednego z nich.
PS: od zawsze bardziej podoba mi się określenie "przeładowanie" zamiast "przeciążenie", pewnie pozostałość po dawnej lekturze Grębosza.
Jeśli przesłaniasz metodę Equls, powinieneś przeciążyć, również operatory ==, != i zastosować w nich ten sam algorytm. Jeśli przesłaniasz metodę Equls musisz również przesłonić GetHashCode().
Problemy:
GetHashCode() zwraca inta, musisz wziąć pod uwagę, że ilość HashCode nie może być większa niż int.MaxValue
HashCody powinny być równomiernie rozłożone, Jeśli nie uwzględnisz tego, że stringi oparte na alfabecie łacińskim pokrywają głównie 128 początkowych znaków ASCII "mieszanie xorgiem" da bardzo nierównomierne wyniki.
Utrudnienie napastnikowi wysłanie do tablicy dużej ilości obiektów o tym samym HashCode co może posłużyć jako atak DoS
Jeśli przesłaniasz Equls, a potem == albo !=, powinieneś wyłącznie używać ReferenceEquals(). Jeśli przeciążasz operator to najczęściej popełnianym błędem oraz najśmieszniejsze jest wykonanie rekurencji przez użycie tego samego operatora jako warunek w ifie.
Afish napisał(a):
Kiedy finally się nie wykona
Jeśli wyjątek nie jest nigdzie złapany (i powoduje crash aplikacji) to nie ma gwarancji wykonania bloku finally.
To dość istotnie ogranicza przydatność bloku finally, który ktoś mógłby sobie wyobrażać jako "na pewno" wykonujący kod niezależnie od tego co się stanie.
throw new Exception()
a ani catch go nie złapie ani finally się nie wykona.
using System;
using System.Windows.Forms;
class Test
{
[STAThread]
static void Main()
{
var form = new Form();
form.Load += (sender, e) => throw new Exception();
try
{
MessageBox.Show("I am still alive.");
Application.Run(form);
}
catch(Exception e)
{
MessageBox.Show("Can't catch this.");
}
finally
{
MessageBox.Show("Finally!");
}
}
}
@Azarien
Zdaje się, że mam rację.
System.Windows.Forms.NativeWindow.Callback
private IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
Message message = Message.Create(hWnd, msg, wparam, lparam);
try
{
if (this.weakThisPtr.IsAlive && this.weakThisPtr.Target != null)
{
this.WndProc(ref message);
}
else
{
this.DefWndProc(ref message);
}
}
catch (Exception e)
{
this.OnThreadException(e);
}
finally
{
if (msg == 130)
{
this.ReleaseHandle(false);
}
if (msg == NativeMethods.WM_UIUNSUBCLASS)
{
this.ReleaseHandle(true);
}
}
return message.Result;
}
A potem w handlerze wyjątku masz:
System.Windows.Forms.Application.ThreadContext.OnThreadException:
ThreadExceptionDialog threadExceptionDialog = new ThreadExceptionDialog(t);
DialogResult dialogResult = DialogResult.OK;
IntSecurity.ModifyFocus.Assert();
try
{
dialogResult = threadExceptionDialog.ShowDialog();
}
finally
{
CodeAccessPermission.RevertAssert();
threadExceptionDialog.Dispose();
}
if (dialogResult != DialogResult.Abort)
{
if (dialogResult == DialogResult.Yes)
{
WarningException ex = t as WarningException;
if (ex != null)
{
Help.ShowHelp(null, ex.HelpUrl, ex.HelpTopic);
}
}
}
else
{
Application.ExitInternal();
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
Environment.Exit(0);
}
Na samym końcu aplikacja jest wyłączana przez Environment.Exit, więc catch na samej górze nie ma żadnego wyjątku do złapania. Finally ciągle się wykonuje, jakby było Environment.FailFast, to nawet on by się nie wykonał.
Właśnie wymyśliłem nowe pytanie:
Czy kolejność pól w klasie/strukturze wpływa na rozmiar zajmowanego przez nią miejsca w pamięci?
Pytanie jest fajne, bo otwiera pole do dyskusji na temat reprezentacji obiektów w pamięci.
neves napisał(a):
Właśnie wymyśliłem nowe pytanie:
Czy kolejność pól w klasie/strukturze wpływa na rozmiar zajmowanego przez nią miejsca pamięci?
Pytanie jest fajne, bo otwiera pole do dyskusji na temat reprezentacji obiektów w pamięci.
o to chodzi?
class First
{
private static int a = 10;
public static long b = CalculateB();
static long CalculateB()
{
return Convert.ToInt64(Math.Pow(a, 10));
}
}
class Second
{
public static long b = CalculateB();
private static int a = 10;
static long CalculateB()
{
return Convert.ToInt64(Math.Pow(a, 10));
}
}
public static void Main(string[] args)
{
Console.WriteLine(First.b);
Console.WriteLine(Second.b);
}
10000000000
0
Jeżeli komuś się nudzi i chce "pozaginać" innych, to jedziemy:
var list = new List<int>();
list.Add(0);
Jaką pojemność będzie miała lista zainicjalizowana w ten sposób przed i po dodaniu pierwszego elementu i jak się będzie zmieniać, oraz dlaczego jeżeli znamy ilość danych, to lepiej zrobić new List<int>(size);
Jeżeli się gdzieś nie walnąłem ofc :P
Dlaczego w ten sposób
var x = new List<int>();
for (long y = 0; y < long.MaxValue; y++)
x.Add(0);
outOfMemory exception leci przy y = 268 435 456
A w ten sposób przy
var x = new List<int>(134217728 * 3);
for (long y = 0; y < long.MaxValue; y++)
x.Add(0);
402 653 184
Jak działa gcAllowVeryLargeObjects
?
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.