Теперь, если название кажется вам странным, рассмотрите этот код, который я просматривал сегодня (упрощенно):
public class MyService(
IHttpClientFactory httpClientFactory) :
BaseService(), // WTF? a Method?
IMyService
{
//no explicit constructor, has default constructor
//....
}
Это действительно компилируется! Класс MyService
наследует что-то от BaseService
, по-видимому, метод, и реализует интерфейс IMyService
.
BaseService
— абстрактный класс, определяющий только некоторые статические объекты и некоторые литеральные строки:
public abstract class BaseService
{
public static List<MaintenanceWindow> RegisteredMaintenanceWindows = new List<MaintenanceWindow>();
protected static string CERT_SERVICE_URI = "https://cert.example.com";
public static string DEFAULT_DOMAIN = "default.example.com";
// ....
}
Что здесь наследует MyService
?
Я никогда не наблюдал такого типа наследования в C#, а также в документации по наследованию от Microsoft об этом не упоминается.
Лично я изучаю большинство новых возможностей языка C#, используя ReSharper, применяя его предложения к своему коду и позже исследуя, что делает «эта новая вещь». Большую часть времени я очень взволнован и рад таким обнаруженным новым функциям.
Бессмысленная и запутанная функция, но неважно...
То, что вы видите, — это новая функция C# — первичные конструкторы. Это позволяет определить класс, а также определить конструктор, встроенный в определение класса:
public class MyClass(string message, string etc)
{
// ... some stuff
}
Это, естественно, расширяется при вызове конструктора базового класса. По старинке было так:
public LineOfCreditAccount(string accountID, string owner, decimal creditLimit)
: base(accountID, owner)
{
_creditLimit = creditLimit;
}
С новым подходом это
public class SavingsAccount(string accountID, string owner, decimal interestRate)
: BankAccount(accountID, owner)
{
// ...
}
В вашем случае конструктор базового класса — это просто конструктор без параметров.
Итак, это все еще старое доброе наследование классов, а не наследование методов.
Ссылка, из которой взяты примеры: Учебник: Изучаем первичные конструкторы
Это стало возможным после введения первичных конструкторов.
Вы можете определить класс следующим образом:
public class Foo(int arg1, int arg2)
{
// ....
}
что (почти) эквивалентно
public class Foo
{
public Foo(int arg1, int arg2)
{
// ...
}
}
Теперь также нужен способ вызова конструктора базового класса из первичного конструктора, и это то, что здесь происходит. В моем примере производный класс может читаться так
public class Derived() : Foo(2,3)
{
// ....
}
Обратите внимание, что при использовании этого синтаксиса необходимо также создать основной конструктор производного класса. ()
не являются обязательными.
Но вы, конечно, можете снова использовать старый стиль:
public class Derived2 : Foo
{
public Derived2()
: base(2, 3)
{
// ....
}
}
Он был добавлен в .net 8 + C#12. Теперь вы можете использовать первичные конструкторы.
// previous
public abstract class BaseService
{
private readonly int _someParam;
public BaseService(int someParam)
{
// some code
_someParam = someParam;
}
}
// same code with primary constructor
public abstract class BaseService(int someParam)
{
private readonly int _someParam = someParam;
}
Итак, если вы не выполняете никаких вызовов методов в своем конструкторе, теперь вы можете написать его таким образом.
Так что это не наследование методов. Это похоже на то, что было до простого наследования классов, с немного большим количеством синтаксического сахара.
Класс не наследует метод.
Обратите внимание, что MyService
имеет первичный конструктор . После имени класса идет список параметров (IHttpClientFactory httpClientFactory)
.
Как и все конструкторы, основной конструктор должен вызвать конструктор базового класса, прежде чем он сможет что-либо сделать. ()
после BaseService
— это синтаксис для вызова конструктора базового класса в первичном конструкторе. ()
— это (n пустой) список параметров.
Это как если бы вы объявили такой конструктор
public MyService(IHttpClientFactory httpClientFactory): base() {
// ...
}
Как и в случае с обычными конструкторами, здесь нет необходимости явно вызывать конструктор базового класса, поскольку BaseService
имеет конструктор без параметров. : base()
можно опустить в приведенном выше фрагменте кода. Аналогично, class MyService(...): BaseService
также допустимо.
Если в базовом классе нет конструктора без параметров, то необходимо добавить (...)
после BaseService
и передать необходимые параметры.
Дополнительную информацию см. в разделе Инициализация базового класса.
Я предпочитаю этот ответ другим, потому что он конкретно касается синтаксиса «Метод-Стиль».
Вопрос: Возможно ли в C# наследование от метода?
О: Нет, это невозможно.
В вашем примере это не наследование методов, это обычное наследование классов.
В C# 12 представлены первичные конструкторы и краткий синтаксис для объявления. конструкторы, параметры которых доступны в любом месте тела тип.
Более подробную информацию можно найти в статье Microsoft — Первичные конструкторы.
Вам нужно прочитать о первичных конструкторах