Segmentação entre plataformas

O .NET moderno suporta vários sistemas operacionais e dispositivos. É importante que as bibliotecas de código aberto do .NET ofereçam suporte ao maior número possível de desenvolvedores, quer estejam criando um site ASP.NET hospedado no Azure ou um jogo .NET no Unity.

Destinos .NET e .NET Standard

Os destinos .NET e .NET Standard são a melhor maneira de adicionar suporte entre plataformas a uma biblioteca .NET.

  • O .NET Standard é uma especificação de APIs do .NET que estão disponíveis em todas as implementações do .NET. O direcionamento do .NET Standard permite que você produza bibliotecas que são restritas a usar APIs que estão em uma determinada versão do .NET Standard, o que significa que ele pode ser usado por todas as plataformas que implementam essa versão do .NET Standard.
  • .NET 6-8 são implementações do .NET. Cada versão é um único produto com um conjunto uniforme de recursos e APIs que podem ser usados para aplicativos da área de trabalho do Windows e aplicativos de console multiplataforma, serviços de nuvem e sites.

Para obter mais informações sobre como o .NET se compara ao .NET Standard, consulte .NET 5 e .NET Standard.

.NET Standard

Se o seu projeto tem como alvo o .NET ou o .NET Standard e compila com êxito, isso não garante que a biblioteca será executada com êxito em todas as plataformas:

  • As APIs específicas da plataforma falharão em outras plataformas. Por exemplo, Microsoft.Win32.Registry terá sucesso no Windows e será lançado PlatformNotSupportedException quando usado em qualquer outro sistema operacional.
  • As APIs podem se comportar de forma diferente. Por exemplo, as APIs de reflexão têm características de desempenho diferentes quando um aplicativo usa compilação antecipada no iOS ou UWP.

Gorjeta

A equipe do .NET oferece um analisador de compatibilidade de plataforma para ajudá-lo a descobrir possíveis problemas.

✔️ COMECE com a inclusão de um netstandard2.0 alvo.

A maioria das bibliotecas de uso geral não precisa de APIs fora do .NET Standard 2.0. O .NET Standard 2.0 é suportado por todas as plataformas modernas e é a maneira recomendada de oferecer suporte a várias plataformas com um destino. Se você não precisa oferecer suporte ao .NET Framework, também pode direcionar o .NET Standard 2.1.

✔️ INCLUA um net6.0 destino ou posterior se você precisar de novas APIs introduzidas em um .NET moderno.

O .NET 6 e aplicativos posteriores podem usar um netstandard2.0 destino, portanto net6.0 , não é necessário. Você deve direcionar net6.0explicitamente , net7.0ou net8.0 quando quiser usar APIs .NET mais recentes.

❌ EVITE incluir um netstandard1.x alvo.

O .NET Standard 1.x é distribuído como um conjunto granular de pacotes NuGet, o que cria um gráfico de dependência de pacote grande e resulta no download de muitos pacotes durante a construção. As implementações modernas do .NET suportam o .NET Standard 2.0. Você só deve direcionar o .NET Standard 1.x se precisar especificamente direcionar uma plataforma mais antiga.

✔️ INCLUA um netstandard2.0 destino se precisar de um netstandard1.x destino.

Todas as plataformas que suportam o .NET Standard 2.0 usarão o netstandard2.0 destino e se beneficiarão de ter um gráfico de pacote menor, enquanto as plataformas mais antigas ainda funcionarão e voltarão a usar o netstandard1.x destino.

❌ NÃO inclua um destino .NET Standard se a biblioteca depender de um modelo de aplicativo específico da plataforma.

Por exemplo, uma biblioteca de kit de ferramentas de controle UWP depende de um modelo de aplicativo que só está disponível na UWP. As APIs específicas do modelo de aplicativo não estão disponíveis no .NET Standard.

Multi-segmentação

Às vezes, você precisa acessar APIs específicas da estrutura de suas bibliotecas. A melhor maneira de chamar APIs específicas da estrutura é usar multi-targeting, que cria seu projeto para muitas estruturas de destino .NET em vez de apenas uma.

Para proteger seus consumidores de terem que criar para estruturas individuais, você deve se esforçar para ter uma saída .NET Standard mais uma ou mais saídas específicas da estrutura. Com você com vários destinos, todos os assemblies são empacotados dentro de um único pacote NuGet. Os consumidores podem então fazer referência ao mesmo pacote e o NuGet escolherá a implementação apropriada. Sua biblioteca .NET Standard serve como a biblioteca de fallback que é usada em todos os lugares, exceto nos casos em que seu pacote NuGet oferece uma implementação específica da estrutura. A multisegmentação permite que você use a compilação condicional em seu código e chame APIs específicas da estrutura.

NuGet package with multiple assemblies

✔️ CONSIDERE direcionar implementações .NET além do .NET Standard.

O direcionamento de implementações .NET permite que você chame APIs específicas da plataforma que estão fora do .NET Standard.

Não abandone o suporte para o .NET Standard quando fizer isso. Em vez disso, lance a partir da implementação e ofereça APIs de capacidade. Dessa forma, sua biblioteca pode ser usada em qualquer lugar e suporta a iluminação de recursos em tempo de execução.

public static class GpsLocation
{
    // This project uses multi-targeting to expose device-specific APIs to .NET Standard.
    public static async Task<(double latitude, double longitude)> GetCoordinatesAsync()
    {
#if NET462
        return CallDotNetFrameworkApi();
#elif WINDOWS_UWP
        return CallUwpApi();
#else
        throw new PlatformNotSupportedException();
#endif
    }

    // Allows callers to check without having to catch PlatformNotSupportedException
    // or replicating the OS check.
    public static bool IsSupported
    {
        get
        {
#if NET462 || WINDOWS_UWP
            return true;
#else
            return false;
#endif
        }
    }
}

✔️ CONSIDERE a multisegmentação, mesmo que o código-fonte seja o mesmo para todos os destinos, quando o projeto tiver dependências de biblioteca ou pacote.

Os pacotes dependentes do projeto, diretos ou downstream, podem usar as mesmas APIs de código enquanto encapsulados em diferentes versões do assembly dependente por estrutura de destino. Adicionar destinos específicos garante que seus consumidores não precisem adicionar ou atualizar seus redirecionamentos de vinculação de montagem.

❌ EVITE a multisegmentação, bem como o direcionamento do .NET Standard, se o código-fonte for o mesmo para todos os destinos e seu projeto não tiver dependências de biblioteca ou pacote.

O assembly .NET Standard será usado automaticamente pelo NuGet. O direcionamento de implementações .NET individuais aumenta o tamanho sem *.nupkg nenhum benefício.

✔️ CONSIDERE adicionar um alvo para net462 quando você estiver oferecendo um netstandard2.0 alvo.

Usar o .NET Standard 2.0 do .NET Framework tem alguns problemas que foram abordados no .NET Framework 4.7.2. Você pode melhorar a experiência para desenvolvedores que ainda estão no .NET Framework 4.6.2 - 4.7.1 oferecendo-lhes um binário criado para o .NET Framework 4.6.2.

✔️ DISTRIBUA sua biblioteca usando um pacote NuGet.

O NuGet selecionará o melhor destino para o desenvolvedor e protegerá que ele tenha que escolher a implementação apropriada.

✔️ DO use a propriedade de um arquivo de TargetFrameworks projeto quando multi-targeting.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!-- This project will output netstandard2.0 and net462 assemblies -->
    <TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
  </PropertyGroup>
</Project>

✔️ CONSIDERE o uso de MSBuild.Sdk.Extras ao multi-targeting para UWP e Xamarin, pois simplifica muito seu arquivo de projeto.

❌ EVITE alterar o nome do assembly ou usar nomes de assembly diferentes para cada TFM que sua biblioteca compila. Devido às dependências entre bibliotecas, a multisegmentação com nomes de assembly diferentes por TFM pode interromper os consumidores de pacotes. Um assembly deve ter o mesmo nome em todos os TFMs.

Alvos mais antigos

O .NET oferece suporte a versões de destino do .NET Framework que estão fora de suporte, bem como plataformas que não estão mais em uso comum. Embora haja valor em fazer sua biblioteca funcionar no maior número possível de destinos, ter que contornar APIs ausentes pode adicionar uma sobrecarga significativa. Tendo em conta o seu alcance e limitações, já não vale a pena visar determinados enquadramentos.

❌ NÃO inclua um destino PCL (Biblioteca de Classes Portátil). Por exemplo, portable-net45+win8+wpa81+wp8.

O .NET Standard é a maneira moderna de oferecer suporte a bibliotecas .NET de plataforma cruzada e substitui PCLs.

❌ NÃO inclua destinos para plataformas .NET que não são mais suportadas. Por exemplo, SL4, WP.