Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ela inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas divergências entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da reunião de design de idioma (LDM).
Você pode saber mais sobre o processo de adoção de speclets de recursos no padrão de linguagem C# no artigo sobre as especificações de .
Problema do especialista: https://github.com/dotnet/csharplang/issues/5529
Resumo
Permitir o uso de um modificador file em declarações de tipo de nível superior. O tipo só existe no arquivo em que ele é declarado.
// File1.cs
namespace NS;
file class Widget
{
}
// File2.cs
namespace NS;
file class Widget // different symbol than the Widget in File1
{
}
// File3.cs
using NS;
var widget = new Widget(); // error: The type or namespace name 'Widget' could not be found.
Motivação
Nossa principal motivação vem dos geradores de código-fonte. Os geradores de origem funcionam adicionando arquivos à compilação do usuário.
- Esses arquivos precisam ser capazes de conter detalhes de implementação que são ocultos do restante da compilação, mas que podem ser usados em todo o arquivo em que são declarados.
- Queremos reduzir a necessidade de os geradores "pesquisarem" nomes de tipo que não colidem com declarações no código do usuário ou código de outros geradores.
Projeto detalhado
- Adicionamos o modificador
fileaos seguintes conjuntos de modificadores: - O modificador de
filesó pode ser usado em um tipo de nível superior.
Quando um tipo tem o modificador file, ele é considerado um tipo de local de arquivo.
Acessibilidade
O modificador file não é classificado como um modificador de acessibilidade. Nenhum modificador de acessibilidade pode ser usado em combinação com file em um tipo.
file é tratado como um conceito independente da acessibilidade. Como os tipos locais de arquivo não podem ser aninhados, somente a acessibilidade padrão internal pode ser usada com tipos file.
public file class C1 { } // error
internal file class C2 { } // error
file class C3 { } // ok
Nomenclatura
A implementação garante que os tipos locais de arquivo em arquivos diferentes com o mesmo nome sejam distintos para o runtime. A acessibilidade e o nome do tipo nos metadados são definidos pela implementação. A intenção é permitir que o compilador adote quaisquer recursos futuros de limitação de acesso no runtime adequados para o recurso. Espera-se que, na implementação inicial, a acessibilidade internal seja utilizada, e um nome impronunciável gerado seja usado, dependendo do arquivo em que o tipo é declarado.
Pesquisa
Alteramos a seção de pesquisa de membro da seguinte maneira (novo texto em negrito):
- Em seguida, se
Kfor zero, todos os tipos aninhados cujas declarações incluírem parâmetros de tipo serão removidos. SeKnão for zero, todos os membros com um número diferente de parâmetros de tipo serão removidos. QuandoKé zero, os métodos que têm parâmetros de tipo não são removidos, uma vez que o processo de inferência de tipo (§11.6.3) pode ser capaz de inferir os argumentos de tipo.- Em seguida, permita que F seja a unidade de compilação que contém a expressão em que a pesquisa de membro está ocorrendo. Todos os membros que são tipos locais de arquivo e não são declarados no F são removidos do conjunto.
- Em seguida, se o conjunto de membros acessíveis contiver tipos locais de arquivo, todos os membros que não são tipos locais de arquivo serão removidos do conjunto.
Comentários
Essas regras não permitem o uso de tipos locais de arquivo fora do arquivo no qual são declaradas.
Essas regras também permitem que um tipo restrito a arquivo tenha um efeito de sombra em um namespace ou um tipo não restrito a arquivo.
// File1.cs
class C
{
public static void M() { }
}
// File2.cs
file class C
{
public static void M() { }
}
class Program
{
static void Main()
{
C.M(); // refers to the 'C' in File2.cs
}
}
Observe que não atualizamos a seção de escopos da especificação. Isso ocorre porque, como diz a especificação:
O escopo de um nome é a região do texto do programa na qual é possível fazer referência à entidade declarada pelo nome sem a qualificação do nome.
Na verdade, o escopo afeta apenas a pesquisa de nomes não qualificados. Este não é exatamente o conceito certo para aproveitarmos porque precisamos também afetar a pesquisa de nomes qualificados:
// File1.cs
namespace NS1
{
file class C
{
public static void M() { }
}
}
namespace NS2
{
class Program
{
public static void M()
{
C.M(); // error: C is not in scope
NS1.C.M(); // ok: C can be accessed through NS1.
}
}
}
// File2.cs
namespace NS1
{
class Program
{
C.M(); // error
NS1.C.M(); // error
}
}
Portanto, não especificamos a característica em termos de qual escopo o tipo está contido, mas sim como "regras de filtragem" adicionais na pesquisa de membros.
Atributos
Classes locais de arquivo têm permissão para serem tipos de atributo e podem ser usadas como atributos dentro de tipos locais de arquivo e tipos não locais de arquivo, como se o tipo de atributo fosse um tipo não local de arquivo. O nome de metadados do tipo de atributo local de arquivo ainda passa pela mesma estratégia de geração de nome que outros tipos locais de arquivo. Isso significa que, provavelmente, a detecção da presença de um tipo local de arquivo por um nome de cadeia de caracteres codificado seja impraticável, pois isso requer a dependência da estratégia interna de geração de nomes do compilador, o que pode mudar ao longo do tempo. No entanto, a detecção por meio de typeof(MyFileLocalAttribute) funciona.
using System;
using System.Linq;
file class MyFileLocalAttribute : Attribute { }
[MyFileLocalAttribute]
public class C
{
public static void Main()
{
var attribute = typeof(C).CustomAttributes.Where(attr => attr.AttributeType == typeof(MyFileLocalAttribute)).First();
Console.Write(attribute); // outputs the generated name of the file-local attribute type
}
}
Uso em assinaturas
Há uma necessidade geral de impedir que tipos locais do arquivo apareçam em parâmetros de membros, retornos e restrições de parâmetros de tipo, onde o tipo local do arquivo pode não estar no escopo no ponto em que o membro é utilizado.
Observe que os tipos não locais de arquivo têm permissão para implementar interfaces locais de arquivo, semelhantes à forma como os tipos podem implementar interfaces menos acessíveis. Dependendo dos tipos presentes nos membros da interface, isso pode resultar em uma violação das regras na seção a seguir.
Permita apenas o uso de assinatura em membros de tipos de arquivos locais
Talvez a maneira mais simples de garantir isso seja impor que os tipos locais de arquivo só possam aparecer em assinaturas ou como tipos base de outros tipos locais de arquivo:
file class FileBase
{
}
public class Derived : FileBase // error
{
private FileBase M2() => new FileBase() // error
}
file class FileDerived : FileBase // ok
{
private FileBase M2() => new FileBase(); // ok
}
Observe que isso restringe o uso em implementações explícitas, mesmo que esses usos sejam seguros. Fazemos isso para simplificar as regras para a iteração inicial do recurso.
file interface I
{
void M(I i);
}
class C : I
{
void I.M(I i) { } // error
}
global using static
É um erro de tempo de compilação usar um tipo local de arquivo em uma diretiva global using static, ou seja,
global using static C; // error
file class C
{
public static void M() { }
}
Implementação/substituições
Declarações de tipo local de arquivo podem implementar interfaces, substituir métodos virtuais etc., assim como declarações de tipo regular.
file struct Widget : IEquatable<Widget>
{
public bool Equals(Widget other) => true;
}
C# feature specifications