статика c # в абстрактном суперклассе будет разделяться между подклассами?

#c# #abstract-class #static-members #ashx

#c# #абстрактный класс #статические элементы #ashx

Вопрос:

я пишу несколько обработчиков ashx, которые подключены к макетной службе, и я хочу, чтобы они совместно использовали экземпляр макетной службы. Самым простым подходом, который я использовал, было создание статического экземпляра

 public class AbstractHandler
    {
        static IService _impl;
        public static IService Impl
        {
            get
            {
                if (_impl == null)
                {
                    _impl = new MockService();
                }
                return _impl;
            }
        }
    }
  

Однако мне интересно, сработает ли это вообще; будут ли разные обработчики, наследуемые от этого класса, иметь свою собственную статическую ссылку _impl или они будут общими?

Ответ №1:

Статическое поле существует один раз, за исключением случая универсального типа, в этом случае оно существует один раз для каждой используемой комбинации универсальных параметров.

Даже если класс является базовым классом, возможно, абстрактным, применяются те же правила. Обратите внимание, что если класс, в котором объявлено поле, не является универсальным, поле будет существовать один раз, даже если потомки являются общими. Правило о «один раз за комбинацию …» вступает в силу только в том случае, если класс, который объявляет статическое поле, является универсальным.

Итак, если бы ваш вопрос вместо этого был:

Как я могу сделать так, чтобы статическое поле было для каждого потомка, а не только один раз

Тогда ответом было бы то, что вы должны были бы сделать свой базовый класс универсальным и передать тип потомка в качестве универсального параметра.

Пример скрипта LINQPad для демонстрации «один раз для каждой общей комбинации параметров»:

 void Main()
{
    var i = new Test<int>();
    var s = new Test<string>();

    Test<bool>.UsageCount.Dump();
    Test<int>.UsageCount.Dump();
    Test<string>.UsageCount.Dump();
}

public class Test<T>
{
    public static int UsageCount;

    public Test()
    {
        UsageCount  ;
    }
}
  

Вывод:

0
1
1

Пример для демонстрации с базовым классом:

 void Main()
{
    var i = new Test1();
    var s = new Test2();

    Test1.UsageCount.Dump();
    Test2.UsageCount.Dump();
    Test3.UsageCount.Dump();
}

public abstract class Base<T>
{
    public static int UsageCount;

    protected Base()
    {
        UsageCount  ;
    }
}

public class Test1 : Base<Test1>
{
}

public class Test2 : Base<Test2>
{
}

public class Test3 : Base<Test3>
{
}
  

Вывод:

1
1
0