В ответ на первый вопрос:
Под капотом расширения действуют как делегаты, так что void MyExtension (этот объект obj) может быть переписан как Action MyDelegate. Однако, где они различаются, это синтаксис при вызове, так как Action должен оборачиваться вокруг объекта, тогда как расширения могут вызываться так, как если бы он был членом самого объекта, даже если он скрыт от него (и не имеет никакого прямой доступ к частным или защищенным членам объекта).
В ответ на второй вопрос:
Я обычно резервирую расширения для классов, которые мне не принадлежат, или для интерфейсов.
Например, скажем, у вас есть интерфейс IAnimal
Public Interface IAnimal
{
void Speak();
void RunToOwnerWhenCalled();
}
И следующие классы
public class Mammal
{
public virtual void AnswerWhatAmI()
{
Console.WriteLine("I'm a mammal");
}
}
public class Dog:Mammal, IAnimal
{
public void Speak()
{
Console.WriteLine("arf");
}
public void RunToOwnerWhenCalled()
{
Console.WriteLine("Comming");
}
}
public class Cat:Mammal, IAnimal
{
public void Speak()
{
Console.WriteLine("meow");
}
public void RunToOwnerWhenCalled()
{
Console.WriteLine("I don't know you");
}
}
Тогда у вас может быть расширение, например
Public static void CallAnimal(this IAnimal animal)
{
animal.RunToOwnerWhenCalled();
}
И такой метод, как
Public static void Main
{
Cat cat = new Cat();
cat.CallAnimal();
}
и результат покажет ответ кота "Я тебя не знаю" в консоли.
Рассмотрим еще один класс
Public class Human:Mammal
{
Public Human():base()
{
Console.WriteLine("To be more specific, I am a human.");
}
}
Этот класс не будет иметь расширения CallAnimal, поскольку он не влияет на интерфейс IAnimal, даже если это тип Mammal.