Laden...

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

Erstellt von Seikilos vor 10 Jahren Letzter Beitrag vor 10 Jahren 4.019 Views
S
Seikilos Themenstarter:in
753 Beiträge seit 2006
vor 10 Jahren
Suche Variable für Filename oder Methode für optionale Argumente (C# 5.0?)

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.

Life is a short

S
Seikilos Themenstarter:in
753 Beiträge seit 2006
vor 10 Jahren

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

Was ich suchte sind die Caller*:


public void Log([CallerMemberName] string Message = "")
{
}

Life is a short

49.485 Beiträge seit 2005
vor 10 Jahren

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

4.931 Beiträge seit 2008
vor 10 Jahren

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).

S
Seikilos Themenstarter:in
753 Beiträge seit 2006
vor 10 Jahren

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

1.346 Beiträge seit 2008
vor 10 Jahren

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); }
        }

    }
49.485 Beiträge seit 2005
vor 10 Jahren

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

S
Seikilos Themenstarter:in
753 Beiträge seit 2006
vor 10 Jahren

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