Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Suche Variable für Filename oder Methode für optionale Argumente (C# 5.0?)
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

Suche Variable für Filename oder Methode für optionale Argumente (C# 5.0?)

beantworten | zitieren | melden

Vor einiger Zeit habe ich über die neuen .net 4.5 und C# 4.0 Features gelesen.
Darunter waren die optionalen Argumente.
Nun wurde in dem Zusammenhang ein nettes Feature aufgeführt, was ich einfach nicht mehr finden kann.

Es ging um eine Möglichkeit logging sehr bequem zu machen. Optionale Argumente sehen ja so aus:


public void Foo(string msg = "irgend ein string") {}

Nun wurde in dem Beispiel eine Signatur benutzt, bei dem der Default Wert scheinbar ein vom Compiler oder Precompiler belegter Wert ist.
Eine Log Signatur sieht dann so aus


public void Log(string method = [Method]) {}

Wenn man dann irgendwo


Log();
benutzt, dann wird vom Compiler [Method] automatisch gefüllt.

Ich habe deutlich die eckigen Klammern in Erinnerung, aber ich finde nirgend die Beschreibung dieses Features.

Entweder ich bringe es durcheinander, oder das war nur Pseudocode.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Seikilos am .
Life is a short
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Ah mist. Es ist C# 5.0 (Hab die Version verwechselt)

Was ich suchte sind die Caller*:


public void Log([CallerMemberName] string Message = "")
{
}
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Seikilos am .
Life is a short
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Seikilos,

in C gab es (für das Logging) es vordefinierte Macros __FILE__ und __LINE__ und ich habe mich immer geärgert, dass es sowas nicht in C# gab und gibt. Noch besser wären natürlich noch weitere Macros wie z.B. __METHOD__ oder __CLASS__. Benötigt hätte ich das u.a. für [Artikel] Attribute zur Prüfung von Properties verwenden. Immerhin gibt es schon seit .NET 1.0 MethodBase.GetCurrentMethod().Name, siehe [Artikel] Attribute zur Prüfung von Properties verwenden.

Aber CallerMemberNameAttribute-Klasse werde ich mir auch mal anschauen. Noch ist mir Verwendung bzw. die genaue Funktionsweise nicht ganz klar.

herbivore
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4177

beantworten | zitieren | melden

Hallo herbivore,

What else is new in C# 5? beschreibt u.a. die neuere Logging-Möglichkeit.

Eine weitere mögliche Verwendung wäre für den Aufruf beim RaisePropertyChanged, s. z.B. C# 5–Making INotifyPropertyChanged Easier, d.h. man muß nicht mehr explizit den eigenen Eigenschaftennamen als string übergeben (sondern der Compiler macht das).
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Hallo herbivore,

das war die Seite mit den Beispielen für Caller Attributes:
An Introduction to New Features in C# 5.0

Die hat nur eine furchtbare Sourceformatierung, aber immerhin sieht man wie Caller Attributes eingesetzt werden können.
Life is a short
private Nachricht | Beiträge des Benutzers
pdelvo
myCSharp.de - Member

Avatar #avatar-3354.png


Dabei seit:
Beiträge: 1407

beantworten | zitieren | melden

Die Caller Attribute sind wirklich sehr praktisch. Besonders wenn man mit MVVM arbeitet. Ich benutze das öfters so:

   public virtual class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void SetValue<T>(ref T field, T value, [CallerMemberName]string propertyName = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                OnPropertyChanged(propertyName);
            }
        }


        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

   public sealed class ServerViewModel : ViewModelBase
    {
        private MainViewModel _model;

        public ServerViewModel()
        {
        }

        internal void SetModel(MainViewModel model)
        {
            _model = model;

        }

        private string _test1;

        public string Test1
        {
            get { return _test1; }
            set { SetValue(ref _test1, value); }
        }

        private string _test2;

        public string Test2
        {
            get { return _test2; }
            set { SetValue(ref _test2, value); }
        }
        private string _test3;

        public string Test3
        {
            get { return _test3; }
            set { SetValue(ref _test3, value); }
        }

    }
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo zusammen,

oben hatte ich ja nur geschrieben, dass ich es noch nicht verstehe, einfach weil ich es mir noch nicht angeschaut hatte. Die nötigen Webseiten hätte ich mir schon selbst herausgesucht. :-) Trotzdem danke ich für die Links. Dadurch wars natürlich bequemer. Und es ist auch praktisch für alle anderen Leser des Threads.

Jetzt habe ich es mir angeschaut und muss sagen, dass ich es immer noch nicht ganz verstehe ... und in Ermangelung von .NET 4.5 hier auf dem (fremden) Rechner auch noch nicht ausprobieren kann.

Wenn es so funktioniert, wie ich vermute, finde ich das zwar praktisch aber (synatktisch) hässlich und unintuitiv. Denn anscheinend muss man den Parameter, auf den man das CallerMemberNameAttribute anwenden will, zwangsläufig als optionalen Parameter deklarieren, und somit auch einen Defaultwert angeben, der dann aber überhaupt nie verwendet wird.

Denn so wie ich es verstehe, gibt es nur zwei Fälle: Der Aufrufer gibt den Parameter explizit an, dann wird diese Angabe genommen. Oder der Aufrufer gibt ihn nicht an, dann wird der Wert des Attributs genommen ... und der Defaultwert eben ignoriert.

Da wäre es schöner, wenn man schreiben könnte:

void M (String caller = [CallerMemberName])

statt

void M ([CallerMemberName]String caller = "Was ich hier angebe, wird eh ignoriert.")

Zugegeben, Attribute werden normalerweise vor die Entität (z.B. Klasse, Methode, ...) geschrieben, die sie attributieren. Aber an allen Stellen, wo das bisher der Fall war, wurden die Attribute dann auch nicht automatisch ausgelesen oder verwendet. Sie waren einfach passive Metadaten, die man bei Bedarf auslesen konnte. Hier aber wird der Wert aus dem Attribut (nämlich der Name des aufrufenden Members) aktiv als Wert für den Parameter verwendet. Dieser Unterschied hätte durchaus eine ausreichende Begründung abgegeben, warum es besser gewesen wäre, das Attribut als Defaultwert anzugeben (SOLL) statt es wie üblich davor zu schreiben (IST).

Möglicherweise wäre es noch besser und klarer gewesen, wenn man ein neues Keyword eingeführt hätte, denn die vorgeschlagene SOLL-Syntax hätte immer noch das Problem, dass der Aufrufer explizit irgendwelchen Mist angeben kann und man sich als aufgerufene Methode nicht darauf verlassen kann, dass man in dem Parameter wirklich den Namen des Aufrufer übergeben bekommt.

herbivore
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Mir geht es da genauso. Als ich im Delirium nach den Attributen gesucht habe, war ich auch der Meinung, dass es so

void M (String caller = [CallerMemberName])
aussehen würde, weil es für mich intuitiv wäre
Life is a short
private Nachricht | Beiträge des Benutzers