none
Get static member of a derived class from an abstract class RRS feed

  • Question

  • Hi everybody,

    I'm working with an abstract class named Animal that has two derived classes : Dog and Cat (to simplify the example). The abstract class has a static string named Desc. Each derived class must have a different value for Desc. I used the following code :

        public abstract class Animal
        {
            public static string Desc;
    
            public static void GetDesc()
            {
                Console.WriteLine("Desc : " + Desc);
            }
        }
    
        public class Cat : Animal
        {
            static Cat()
            {
                Cat.Desc = "Beautiful small animal";
            }
        }
    
        public class Dog : Animal
        {
            static Dog()
            {
                Dog.Desc = "Big animal";
            }
        }

    I would like that :

    • Dog.GetDesc() show "Desc : Big animal"
    • Cat.GetDesc() show "Desc : Beautiful small animal"

    Of course, it doesn't work like this.
    How could I do that ?

    I know it is difficult to understand why I want to do this. In fact, I use an abstract class in a project to work with a database : each derived class is a table and I want to store names of stored procedures in static members of each class.

    Thanks in advance for your suggestions.


    • Edited by NicolasC Tuesday, November 6, 2012 8:35 PM
    Tuesday, November 6, 2012 8:31 PM

Answers

  • The Desc field is stored at the Animal class level. When the Dog static constructor is invoked, the Animal.Desc field is changed. What you need is to keep a distinct field for each class. Generics can help you:
    public abstract class Animal<T> where T : Animal<T>
    {
        public static string Desc;
        public static void GetDesc()
        {
            Console.WriteLine("Desc : " + Desc);
        }
    }
    public class Cat : Animal<Cat>
    {
        static Cat()
        {
            Cat.Desc = "Beautiful small animal";
        }
    }
    public class Dog : Animal<Dog>
    {
        static Dog()
        {
            Dog.Desc = "Big animal";
        }
    }

    Now, you have two independent fields: Animal<Cat>.Desc, and Animal<Dog>.Desc.
    • Edited by Louis.fr Wednesday, November 7, 2012 2:27 PM
    • Marked as answer by NicolasC Monday, November 12, 2012 7:11 PM
    Wednesday, November 7, 2012 2:27 PM

All replies

  • It can work.  You have to understand when the static constructor is called.  It is called the first time a class is referenced.   The static constructor will not be called until "something" in Dog or Cat is called first.  Either a default constructor, or a method etc...

    try this example to see:

    using System;
    
        public abstract class Animal
        {
            public static string Desc;
    
            public static void GetDesc()
            {
                Console.WriteLine("Desc : " + Desc);
            }
        }
    
        public class Cat : Animal
        {
            static Cat()
            {
                Cat.Desc = "Beautiful small animal";
            }
        }
    
        public class Dog : Animal
        {
            static Dog()
            {
                Dog.Desc = "Big animal";
            }
        }
    
    public static class Example
    {
    
      public static void Main(string[] args)
      {
         Console.WriteLine("1 " + Dog.Desc);
         Dog dog = new Dog();
         Console.WriteLine("2 " + Dog.Desc);
    
      }
    
    }

    you will see that the output is:

    1
    2 Big animal

    Put break points in the code.  This will help you see when the static constructors are actually called.

    Matt


    • Edited by tatman blue Tuesday, November 6, 2012 10:19 PM
    Tuesday, November 6, 2012 9:59 PM
  • Hi Matt,

    For the static constructor, I already planned in the real case to call the class at the begin of the program to initialize the static member.

    But I need to access to this static member from a method of the abstract class.
    Is there a way to do this ?

    Maybe not, I'm not sure...

    Wednesday, November 7, 2012 5:58 AM
  • namespace CSharp
    {
        public abstract class Animal
        {
            public static string Desc;
    
            public static void GetDesc()
            {
                Console.WriteLine("Desc : " + Desc);
            }
        }
    
        public class Cat : Animal
        {
            static Cat()
            {
               Desc = "Beautiful small animal";
            }
        }
    
        public class Dog : Animal
        {
            static Dog()
            {
                Desc = "Big animal";
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Animal a = new Cat();  //This will change the new Cat
                Animal.GetDesc();
            }
        }
    }

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    Wednesday, November 7, 2012 6:09 AM
  • The Desc field is stored at the Animal class level. When the Dog static constructor is invoked, the Animal.Desc field is changed. What you need is to keep a distinct field for each class. Generics can help you:
    public abstract class Animal<T> where T : Animal<T>
    {
        public static string Desc;
        public static void GetDesc()
        {
            Console.WriteLine("Desc : " + Desc);
        }
    }
    public class Cat : Animal<Cat>
    {
        static Cat()
        {
            Cat.Desc = "Beautiful small animal";
        }
    }
    public class Dog : Animal<Dog>
    {
        static Dog()
        {
            Dog.Desc = "Big animal";
        }
    }

    Now, you have two independent fields: Animal<Cat>.Desc, and Animal<Dog>.Desc.
    • Edited by Louis.fr Wednesday, November 7, 2012 2:27 PM
    • Marked as answer by NicolasC Monday, November 12, 2012 7:11 PM
    Wednesday, November 7, 2012 2:27 PM