Devo colocar métodos de extensão de uma interface no arquivo interface.cs?


8

Imagine esta configuração:

public interface IMass{
    double Mass {get;}
}

public static class IMassExtension {
    public static double ToKg(this IMass massObject) {
        return massObject.Mass / 1000.0;
    }

    public static double CalculateInteractiveGravity(this IMass massObject, IMass otherMassObject)          
    {
         return blah;
    }
}

Posso colocar a classe de extensão no mesmo arquivo da interface (por exemplo, IMass.cs) ou em um arquivo separado (IMassExtension.cs)?


Uma classe base não é possível aqui. Imagine

public class Person : Animal, IMass {}

e

public class House : Building, IMass {}

Classe @Yusubov base não vai funcionar aqui, pergunta atualizados
— Moop

Respostas:


13

Sim, está tudo bem. Além disso, eu encorajo você a fazer isso, pois torna a funcionalidade disponível na interface mais detectável, enquanto reduz o ruído no "que funcionalidade há neste csproj?" vista no visual studio.

Os únicos argumentos que ouvi contra isso são:

  • "mas então você tem 2 tipos por arquivo!" - existem orientações para ajudá-lo, não para amarrar as mãos. Você faria apenas um tipo, se pudesse.
  • "mas essa extensão usa XYZ!" - sim, se você não incluir o método se for uma classe abstrata, também não deverá conectá-lo à interface. Isso não é um problema com essa prática, mas com o seu design.

Novos recursos de idioma melhoram isso ainda mais
— user1496062 14/04

2

Em resumo: ter os métodos de extensão em um arquivo separado seria a melhor solução. Também é muito importante nomear as extensões adequadamente, pois isso definitivamente garantirá um tempo seguro durante a manutenção.

Eu definitivamente preferem o nome MassExtensionsmais IMassExtensions. A razão é que, para a maioria dos programadores, um prefixo I em um tipo implica que é uma interface. Esse é um padrão muito comum e faz parte das Diretrizes de Design do .NET.

A adição de um prefixo I para o caso do método de extensão quebra as suposições e as diretrizes estabelecidas.

Também há precedência para isso na Biblioteca de Classes Base. A maior parte dos métodos disponíveis para extensão IEnumerableestão contidos no tipo Enumerable.

As seguintes postagens relacionadas podem ser úteis:


Esta publicação do blog recomenda no mesmo espaço para nome: blogs.msdn.com/b/vbteam/archive/2007/03/10/…
— Moop

Concordo, deve haver em seus próprios espaços para nome
— Yusubov

1

Normalmente, eu não colocaria métodos de extensão no mesmo arquivo que a interface. Mesma biblioteca / pacote? Certo.

Neste exemplo, eu definitivamente não. E se alguém implementasse massa em unidades imperiais (lesmas)? O toKg () deve estar na interface (e talvez bem como toSlug (), mas tecnicamente seria derivável de toKg ()), e os métodos de extensão seriam métodos como toG (), toMcg (), etc., que pode ser implementado usando os métodos de interface.


0

Eu o colocaria em um arquivo separado e daria a ele um nome mais descritivo que "IMassExtension.cs". Talvez algo como "MassConversions.cs", já que é isso que a classe realmente faz.

Não se esqueça, os métodos de extensão ainda podem ser chamados como se fossem métodos estáticos simples (por exemplo MassConversions.ToKg(massObject)), portanto, a classe deve ser nomeada com isso em mente. Além disso, sua classe de extensão não é uma interface, portanto, pode ser enganoso nomeá-la com o 'I' principal.


Bem, este é apenas um exemplo simples, eu tenho vários métodos de extensão que fazem coisas diferentes, e não existe um bom nome comum para isso
— Moop

Isso pode ser um sinal de que alguma reflexão adicional deve ser colocada na organização da funcionalidade. As aulas de "pia da cozinha" geralmente são fontes de muita agonia e geralmente devem ser evitadas. Só porque a funcionalidade é apresentada na forma de métodos de extensão, não há motivo para abandonar uma boa estrutura de classes.
— Eric King

Atualizei a pergunta para mostrar uma possível razão pela qual ela é útil para esse design.
— Moop

Vejo sua atualização e meu comentário ainda se aplica. Crie classes separadas (nomeadas apropriadamente) para tipos separados de funcionalidade. Na minha opinião, colocar todos eles na mesma classe é conveniente, mas desleixado.
— Eric Rei

Você está dizendo isso Animial : Masse Building : Massse Massera uma classe base?
— Moop
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.