TOC

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

Classes:

Local functions

We learned in previous articles that methods and properties belong to classes in C#. Inside methods, you can have local variables, which are variables only accessible in the scope of this specific method. This makes sense because you'll often have temporary data you need to store, but which shouldn't be accessible from other classes or even other methods in the same class. Previously, you couldn't do the same thing with methods - if a method was declared on a class, it could, at least, be accessed from other methods within the same class, but in C# version 7, the concept of local functions were introduced.

Uma local function é declarada dentro de um método existente, e só pode ser acessada de dentro deste método. Isso encapsula as funcionalidades e torna mais claro para qualquer leitor do seu código que essa funcionalidade só é relevante para aquele método. Uma local function se parece com um método comum, mas sem o modificador de visibilidade, já que a local function é acessível apenas de dentro do método que a contém.

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 local function (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.

As you can see in my example, I declare the local function in the start of the method. You are free to change this, e.g. by declaring it in the middle or the end of the method. Only in one case will it make a difference: A local function is allowed to access variables declared inside the declaring method, but only if they have been declared before the local function. So if you want to take advantage of this behavior, you will have to modify the method, e.g. like this:

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]);
	}
	....
}

Summary

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!