Laden...

Wann verwendet man static?

Erstellt von sane vor einem Jahr Letzter Beitrag vor einem Jahr 678 Views
S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr
Wann verwendet man static?

Servus zusammen, bitte lyncht mich für den folgenden Beitrag nicht, aber mir ist immer noch nicht klar war ich einen Member zum KlassenMember machen soll und wann er definitiv zur Instanz gehört. ich würde es um einiges leichter finden, wenn ich einfach alles zugehörig zur Instanz machen könnte. Einfach felder und Eigenschaften definieren und diese in den Methoden ohne Parameter zu übergeben aufrufen könnt. Ich kann mir aber vorstellen, dass Aufgrund von Performance, GarbageCollector.... das so nicht gehandabt wird.

Wie soll ich da vorgehen? ich stelle mir immer die Frage, ob es zur definition der Klasse benötigt wird, aber leider fehlt es mir am Regelwerk, weil ich immer eine begründung finde, es static zu machen. Verursacht aber teilweise extreme schreibarbeit, weil ich Paramter übergeben muss und dies bei jedem aufruf- wenn ich eine statische- in einer statischen Methode aufrufe, dann muss ich die Parameter teilweise zweimal übergeben. macht das sinn?

nur so als annahme. Man schreibt ein Programm wo geometrisch das eine oder ander bearbeitet, errechnet, gestaltet werden kann. somit kommt man sicherlich nicht um die Addition, Fläche herum. G
Genau das gleiche ist mit Parametern, warum übergibt man Parameter

sorry für die dummen Fragen.


static int Addition(int num1, int num2)
        {
            return num1 + num2;
        }

        static int Umfang(int num1, int num2)
        {
            return Addition(num1, num2) * 2;
        }

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

in Bezug auf Performance hab ich gelesen, dass statische Member nur einmal erstellt werden und diese im Heap sind, InstanzMember jedesmal. das ist unter anderem etwas, warum ich mir denke, dass dieses Thema nicht einfach so Beiseite geschoben werden kann.

T
2.224 Beiträge seit 2008
vor einem Jahr

Ich muss ehrlich gestehen, dass ich deine Frage, wofern dein Beitrag eine enthält, nicht verstehe.
Will du wissen wann man static nutzt und wann nicht?

static sollte man nur bei Klassen/Methoden verwenden, wenn diese z.B. Wrapper für nativen Code (P/Invoke) oder Hilfsmethoden liefern.
Ein Beispiel dafür ist z.B. die Math Klasse von .NET die dir grundlegende Rechnen Methoden anbietet.

static sollte man aber nicht generell oder übermäßig nutzen.
Es macht keinen Sinn jede Klasse/Methode mit static zu markieren.
Es gibt einfach Daten die man eben per Instanz haben muss.
Ob es dann z.B. nur eine Instanz (Singleton) oder mehrere Instanzen geben kann, hängt jeweils von dem Zweck ab.

Es kann aber auch sinnvoll sein gewisse Operationen und Berechnungen in Klassen zu Kapseln und dort für die jeweiligen Instanzen zu verwenden.
Auch in deinem Beispiel könnte man z.B. Kreise o.ä. als eigene Instanzen haben.
Die Eigenschaften können dann die Fläche/Umfang etc. berechnen und liefern.
Dazu muss man keine static Methoden haben, was auch kontraproduktiv wäre weil man dann beides vermischen müsste wenn man mehrere Instanzen benötigt z.B. in einem Zeichenprogramm.

Nachtrag:
Zu deinem Performance Post.
Bei static Klassen/Mehtoden muss für die jeweilige Klasse eine statische Instanz vorliegen um auf die statischen Methoden zuzugreifen.
Wenn die Klasse selbst aber nicht als static markiert ist, dann kann diese immer noch regulär instanziert werden.
Dies spielt aber für die Performance keine Rolle.

Wenn du nur eine oder wenige Instanzen von deinen Klassen hast, spielt dies nur beim erzeugen eine Rolle hat aber selten Auswirkungen auf die Performance.
Es kann aber u.U. teuer sein Instanzen zu erstellen, wenn diese z.B. Daten von langsamene Quellen abrufen müssen beim erzeugen.
Z.B. wenn beim erstellen einer Instanz Abfragen gegen OS Schnittstellen laufen die pro Aufruf auch mehrere Millisekunden benötigen.
Wenn du nur wenige Instanzen hast, mag das nicht ins Gewicht fallen sobald du aber einige Tausend davon erstellen willst, macht sich dies bemerkbar.

I.d.R. kostet die Erstellung von Objekten etwas Rechenzeit und zusätzlichen Speicher (RAM).
Aus heutiger Sicht sind aber schon die schwächten Systeme leistungsfähig genug um damit ohne Probleme umzugehen.
Nur wenn man es übertreibt, kann es dann eben zu hoher Last bei CPU und RAM Verbrauch kommen.

Wegen einiger weniger Instanzen musst du dir wegen Performance kaum Sorgen machen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.835 Beiträge seit 2008
vor einem Jahr

Du kannst Deinen eigenen Beitrag 30 Minuten lang editieren - darfst auch Du nutzen, wenn Du noch was hinzufügen willst 😉

Du bist in C# in einer OOP Umgebung, es ist daher ratsam sich an die Grundregeln von OOP zu halten, wozu gehört, dass man static vermeidet, wann immer es geht.
Static sollte also bewusst für Dinge verwendet werden, die selbst nicht zum OOP Kontext gehören.

Die Performance-Auswirkungen von static (in beide Richtungen) gelten zu den Micro-Optimierungen. Ist also in 99,999% der Fälle irrelevant; vermutlich auch für Dein Level.


In Deinem Beispielfall ist für mich die Anwendung vom Funktionsaufruf totaler Käse, weil Du eine sehr günstige Operation durch eine vergleichsweise teure Funktion ersetzt.
Warum? Das macht weder die Logik noch die Performance besser. Das kann man auch mit einem sehr simplen Benchmark nachvollziehen


[SimpleJob(RuntimeMoniker.Net70)]
public class Benchmark
{
    [Benchmark]
    public int Umfang_1() => MyStatic.Umfang_1(7, 8);

    [Benchmark]
    public int Umfang_2() => MyStatic.Umfang_2(7, 8);
}

public static class MyStatic
{
    public static int Addition(int num1, int num2)
    {
        return num1 + num2;
    }

    public static int Umfang_1(int num1, int num2)
    {
        return Addition(num1, num2) * 2;
    }

    public static int Umfang_2(int num1, int num2)
    {
        return (num1 + num2) * 2;
    }
}

Job=.NET 7.0 Runtime=.NET 7.0

Method Mean Error StdDev Median
Umfang_1 0.2012 ns 0.0163 ns 0.0152 ns 0.1998 ns
Umfang_2 0.0043 ns 0.0006 ns 0.0002 ns 0.0037 ns

Kannst im Maschinencode auch den teuren Absprung sehen, der hat nicht optimiert werden kann:

MyStatic.Umfang_1(Int32, Int32)
L0000: push ebp
L0001: mov ebp, esp
L0003: sub esp, 0x10
L0006: xor eax, eax
L0008: mov [ebp-0xc], eax
L000b: mov [ebp-4], ecx
L000e: mov [ebp-8], edx
L0011: cmp dword ptr [0x1e6bc190], 0
L0018: je short L001f
L001a: call 0x71cc5060
L001f: nop
L0020: mov ecx, [ebp-4]
L0023: mov edx, [ebp-8]
** L0026: call MyStatic.Addition(Int32, Int32)**
L002b: mov [ebp-0x10], eax
L002e: mov eax, [ebp-0x10]
L0031: add eax, eax
L0033: mov [ebp-0xc], eax
L0036: nop
L0037: jmp short L0039
L0039: mov eax, [ebp-0xc]
L003c: mov esp, ebp
L003e: pop ebp
L003f: ret

MyStatic.Umfang_2(Int32, Int32)
L0000: push ebp
L0001: mov ebp, esp
L0003: sub esp, 0xc
L0006: xor eax, eax
L0008: mov [ebp-0xc], eax
L000b: mov [ebp-4], ecx
L000e: mov [ebp-8], edx
L0011: cmp dword ptr [0x1e6bc190], 0
L0018: je short L001f
L001a: call 0x71cc5060
L001f: nop
L0020: mov eax, [ebp-4]
L0023: add eax, [ebp-8]
L0026: add eax, eax
L0028: mov [ebp-0xc], eax
L002b: nop
L002c: jmp short L002e
L002e: mov eax, [ebp-0xc]
L0031: mov esp, ebp
L0033: pop ebp
L0034: ret

Die Operation hingegen kann optimiert werden, direkt auf Aufrufebene.

In anderen Fällen kann so ein Function Chaining okay sein - hier in meinen Augen totaler Käse, in allen Belangen 🙂


Fazit

Lass solche Micro Evil Dinger sein, und verwende static so, wie es in der Sprache vorgesehen ist.
static-Modifizierer – C#-Referenz

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

Danke T-Virus für deine Antwort. Es kann gut sein, dass ich anfange alles zu verkomplizieren.

anbei ein Beispiel. Würde man die statische Methode überhaupt static machen? muss, aber ohne würde auch gehen.

Weil das Schlagwort Kreis gefallen ist


class Kreis
    {
        double radius;
        public double Radius
        {
            get { return radius; }
            set { radius = value; }
        }
        //macht man es nun so?
        public double Durchmesser
        {
            get { return DefDurchmesser(radius); }
        }
        public double Umfang { get; set; }
        public double Flaeche { get; set; }

        public Kreis(double radius)
        {
            Radius = radius;
            //oder so?
            Umfang = DefUmfang();
        }

        static double DefDurchmesser(double radius)
        {
            return radius * 2;
        }

        double DefUmfang()
        {
            return DefDurchmesser(radius) * Math.PI;
        }
        // oder so.
        void DefFlaeche()
        {
            Flaeche = Durchmesser * Durchmesser * Math.PI / 4;
        }
    }

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

Danke Abt für deine Antwort. für mich gibt es kein static mehr!

Ich hab die Addition nur aufgerufen, weil bei mir immer im Hinterkopf ist, dass es wiederverwendbar sein soll. Schreibe oft klassen wo ich nur eine kleinigkeit ausführe, wo mich der Aufruf der Klasse womöglich mehr resourcen kostet, wie wenn ich kurz eine Methode schreiben würde. Werd ich auch lassen.

16.835 Beiträge seit 2008
vor einem Jahr

Das eine ist static, das andere ist Wiederverwendbarkeit.
Wiederverwendbarkeit hat seine Berechtigung und soll getan werden (Dont Repeat Yourself) - aber ein "+" wegzuoptimieren geht in diesem Fall nach Hinten los und hat auch keinerlei Berechtigung.
Selbst aus einer simplen Addition eine ganze Methode zu machen ist schon extrem fragwürdig.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@Abt danke für deine Antwort.

Wie soll ich sagen. Es ist nicht so einfach es, vorallem als anfänger anzuschätzen was richtig und falsch ist. Weil so wie ich es gelernt habe, soll eine Methode nur einen Auftrag erledigen. Verleitet, wenn man die Methode dann schreibt sehr oft dazu, dass die Methode zu lange wird, was vielleicht in einer anderen Methode definiert werden hätte können, oder sollen.....

M
368 Beiträge seit 2006
vor einem Jahr

...static...

Klassen dienen zum Herstellen von Zusammenhängen zwischen Methoden und Objekten (1). Eine statische Methode oder Variable soll diese Eigenschaft aber gerade nicht erfüllen (auch wenn der C#-Compiler eine formelle Definition innerhalb einer Klasse erwartet (2)).

(1)youtube.com, Kanal "thenativeweb", "Warum OOP (objektorientierte Programmierung) überbewertet ist" (ab 3:03) (tendenziell religiöse Ansichten...)
(2)youtube.com, Kanal "thenativeweb", "5 Gründe, warum C# Murks (und nicht mehr so ganz zeitgemäß) ist" (ab 13:14 oder 14:49) (auch tendenziell religiöse Ansichten...)

Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉

16.835 Beiträge seit 2008
vor einem Jahr

Ich finde beide Videos inhaltlich sehr schwierig.... finde ich kein gutes Placement hier (meine Meinung).

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@M.L danke für deinen Beitrag.