none
Call to virtual method warning in Konstruktor RRS feed

  • Frage

  • Hallo,

    leider laufe ich in eine Serie von Warnungen des gleichen Typs in meiner C# Wpf (ich benutze das MVVM Light ToolKit) Anwendung und finde/verstehe deren Ursache einfach nicht.

    Hier ist meine Fehlermeldung:

    Severity    Code    Description    Project    File    Line
    Warning    CA2214    'AnlageTyp.AnlageTyp(string, ObservableCollection<Header>)' contains a call chain that results in a call to a virtual method defined by the class. Review the following call stack for unintended consequences:

    AnlageTyp..ctor(String, ObservableCollection<Header>)
    AnlageTyp.set_Title(String):Void
    ObservableObject.RaisePropertyChanged(String):Void    KapaTool    C:\Users\dennis\documents\visual studio 2015\Projects\KapaTool\KapaTool\Model\AnlageTyp.cs    46

    Laut google greife ich in einem Konstruktor auf eine virtual method zu, was aber eigentlich nicht der Fall ist da ich nur eine property Title mit dem qualifizierten setter zuweise.

    Code:

    using System.Collections.ObjectModel;
    using GalaSoft.MvvmLight;
    using KapaTool.Services;
    
    namespace KapaTool.Model
    {
        public class AnlageTyp : ObservableObject, IInstanceIdentifier
        {
            #region Attributes
    
            public ObservableCollection<Linie> Linien { get; set; }
    
            public LinienÜbersicht LinienÜbersicht { get; set; }
    
            /// <summary>
            /// The <see cref="Title" /> property's name.
            /// </summary>
            public const string TitlePropertyName = "Title";
    
            private string _title;
    
            /// <summary>
            /// Sets and gets the Title property.
            /// Changes to that property's value raise the PropertyChanged event. 
            /// </summary>
            public string Title
            {
                get { return _title; }
    
                set
                {
                    if (_title == value)
                    {
                        return;
                    }
    
                    _title = value;
                    RaisePropertyChanged(TitlePropertyName);
                }
            }
    
            #endregion
    
            #region Constructors
    
            public AnlageTyp(
                string title,
                ObservableCollection<Header> headers 
                )
            {
                Title = title;
    
                Linien = new ObservableCollection<Linie>();
                
                LinienÜbersicht = new LinienÜbersicht(headers);
            }
    
            #endregion
    
            #region overrides
    
            public override string ToString() => Title;
    
            #endregion
    
            #region IInstanceIdentifier Impl
    
            public long Id { get; set; }
    
            #endregion
    
            #region Methodes
    
            public void AddAndUpdate(RepositoryService repository, string title,
                ObservableCollection<Header> headers,
                FilterBegriff filterBegriff,
                Absatzplan filteredAbsatzplan
                )
            {
                var item = new Linie(title, headers, filterBegriff, filteredAbsatzplan);
    
                Linien.Add(item);
    
                repository.SaveOrUpdate(item);
            }
    
            #endregion
    
        }
    }
    

    Ist die Warnung ernstzunehmen? Falls ja wodurch wird Sie verursacht und wie kann ich die Codeschwäche verbessern?

    Mittwoch, 14. Oktober 2015 20:25

Antworten

  • Hallo eCazz,

    Die Implementierung der RaiseProperty methode ist von der abstracten Klasse ObservableObject geerbt.

    ObservableObject ist laut Dokumentation keine abstrakte Klasse. Wenn Du die Methode versiegelst, kann sie nicht mehr geerbt werden. Wirst Du dadurch die Warnung los? Oder indem Du die von Holger empfohlene Verlagerung umsetzt?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    • Als Antwort markiert eCazz Freitag, 30. Oktober 2015 12:55
    Donnerstag, 22. Oktober 2015 11:58
    Administrator

Alle Antworten

  • Hallo eCazz,

    greife ich in einem Konstruktor auf eine virtual method zu, was aber eigentlich nicht der Fall ist

    Wie ich Deinem Code und der Aufrufliste entnehmen kann, wird RaisePropertyChanged(TitlePropertyname) beim Zuweisen der Title aufgerufen. Diese Methode ist jedoch als virtuell deklariert:

    protected virtual void RaisePropertyChanged(string propertyName);

    Ich würde Dir vorschlagen, einen dieser Ansätze umzusetzen:

    1. Du kannst die Methode in Deiner Klasse überschreiben und versiegeln:
          protected override sealed void RaisePropertyChanged(string propertyName)
          {
              base.RaisePropertyChanged(propertyName);
          }
    2. Oder Du kannst die ganze Klasse AnlageTyp als sealed kennzeichnen.

    Verschwindet dadurch die Warnung? Sieh Dir dazu diese Threads an, die Aufschluss über die Besonderheiten dieses Themas geben:
    StyleCop issue needs resolving - contains a call chain that results in a call to a virtual method defined by the class
    Virtual member call in a constructor

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Donnerstag, 15. Oktober 2015 20:20
    Administrator
  • Hallo,
    ist hier sehr gut und sehr ausführlich erklärt: http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor

    Ach übrigens. Die Warnungen sollten immer ernst genommen werden. Ich betrachte jede Warnung wie einen Fehler. Dies sollte man sich spätestens beim komplieren des Release zu Herzen nehmen.


    Viele Grüße Holger M. Rößler


    Donnerstag, 15. Oktober 2015 20:50
  • Hallo,

    erstmal Danke für die Antworten.

    Die Implementierung der RaiseProperty methode ist von der abstracten Klasse ObservableObject geerbt. Dieses Observable Object wird durch das Framework MVVMLight toolkit implementiert, weshalb ich mich nicht so sicher dabei fühle die Implementierung in sealed umzuändern.

    Montag, 19. Oktober 2015 09:44
  • Hallo,
    die Methode zu versiegeln ändert nichts an deinem Problem. Diese Methode ist abstrakt und damit implizit virtuell.

    Da Vererbungshierarchien komplett fixe Strukturen sind, wird sich das nur durch Verlagerung des Codefragments zu einem Zeitpunkt nach der Objektkonstruktion lösen lassen.


    Viele Grüße Holger M. Rößler

    Montag, 19. Oktober 2015 10:42
  • Hallo eCazz,

    Die Implementierung der RaiseProperty methode ist von der abstracten Klasse ObservableObject geerbt.

    ObservableObject ist laut Dokumentation keine abstrakte Klasse. Wenn Du die Methode versiegelst, kann sie nicht mehr geerbt werden. Wirst Du dadurch die Warnung los? Oder indem Du die von Holger empfohlene Verlagerung umsetzt?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    • Als Antwort markiert eCazz Freitag, 30. Oktober 2015 12:55
    Donnerstag, 22. Oktober 2015 11:58
    Administrator
  • Hallo,

    das versiegeln der Methode hat die Warnungen gestoppt. Danke hatte schon ein schlechtes Gewissen da ich die Warnungen ignoriert habe :)

    Best,

    eCazz

    Freitag, 30. Oktober 2015 12:56