TOC

This article is currently in the process of being translated into Portuguese (~82% done).

Classes:

Local functions

Aprendemos nos artigos anteriores que métodos e propriedades pertencem as classes em C#. Dentro dos métodos, você pode ter variáveis locais, que são variáveis que só podem ser acessadas no escopo desse método em específico. Isso faz sentido pois você provavelmente vai ter um dado temporário que precisa armazenar, mas que não poderia ser acessado por outras classes e nem por outro métodos na mesma classe. Anteriormente, você não podia fazer a mesma coisa com métodos - se um método foi declarado em uma classe, ele poderia, pelo menos, ser acessado por outro método dentro da mesma classe, mas em C# versão 7, o conceito de local functions foram apresentados.

Uma função local é declarada dentro de um método existente, e só pode ser acessada por esse método. Isso encapsula firmemente as funcionalidades e também torna mais claro para qualquer leitor do seu código que essa funcionalidade só é relevante para aquele método declarado. Uma função local se parece com um método comum, mas sem o modificador de visibilidade, já que a função local sempre só é acessível se estiver dentro do método declarado. Aqui um exemplo:

public void MethodWithLocalFunction()
{
	bool doesNameStartWithUppercaseChar(string name)
	{
		if(String.IsNullOrEmpty(name))
			throw new Exception("name parameter must contain a value!");
		return Char.IsUpper(name[0]);
	}

	List<string> names = new List<string>()
	{
		"john doe",
		"Jane doe",
		"dog Doe"
	};

	foreach(string name in names)
		Console.WriteLine(name + " starts with uppercase char: " + doesNameStartWithUppercaseChar(name));
}

Um exemplo um tanto simples, mas que demonstra como se pode declarar uma função local (nesse caso chamada de doesNameStartWithUppercaseChar) dentro de um método (chamado de MethodWithLocalFunction) e então chamá-la uma ou várias vezes de dentro do método.

Como você pode ver no meu exemplo, declarei a função local no início do método. Você está livre para alterar isso, por exemplo declarando no meio ou no final do método Só em um caso fará a diferença: Uma função local tem permissão para acessar as variáveis declaradas dentro do método declarado, mas só se elas foram declaradas antes da função local. Então se você quer ter vantagem disso, você precisa mudar o método, por exemplo assim:

public void MethodWithLocalFunction()
{
	int nameMaxLength = 10;

	List<string> names = new List<string>()
	{
		"john doe",
		"Jane doe",
		"dog Doe"
	};

	foreach(string name in names)
		Console.WriteLine(name + " starts with uppercase char: " + doesNameStartWithUppercaseChar(name));

	bool doesNameStartWithUppercaseChar(string name)
	{
		if(String.IsNullOrEmpty(name))
			throw new Exception("name parameter must contain a value!");
		if(name.Length > nameMaxLength)
			throw new Exception("name is too long! Max length: " + nameMaxLength);
		return Char.IsUpper(name[0]);

	}
}

Observe como eu declaro a variável nameMaxLenght dentro do método e depois a acesso dentro da função local.

Static local functions

In C# version 8, support for static local functions were added. As of writing, the only difference between a regular and a static local function is the fact that a static local function can't use variables from the declaring method - in other words, they no longer share scope. So if you want to make sure that your local function can't reference or change variables from the method, just declare it as static, like this:

public void MethodWithLocalStaticFunction()
{
	int nameMaxLength = 10;
	
	static bool doesNameStartWithUppercaseChar(string name)
	{
		// Local variables, e.g. nameMaxLength, are no longer accessible here....
		if(String.IsNullOrEmpty(name))
			throw new Exception("name parameter must contain a value!");
		return Char.IsUpper(name[0]);
	}
	....
}

Resumo

Em algumas situações, local functions podem ser uma ajuda e tanto quando você precisa encapsular e reutilizar alguma funcionalidade específica. Como alternativa, se a funcionalidade puder ser reutilizada vinda de outros métodos, considere adicioná-la como um método em uma helper class, ou como um método estendido.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!