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.