Option<T>
Esta classe representa valores opcionais.
Instâncias de Option<T>
encapsulam um valor que pode ou não existir. Este valor só pode ser acessado através dos métodos Match
e Match2
.
Os valores opcionais são considerados no estado de IsNone
(não contendo nada) quando o valor armazenado nele é igual à null
ou ao valor default
de seu respectivo tipo.
Propriedades
Nome | Tipo | Descrição |
---|---|---|
IsSome | bool | Retorna true quando o valor contido no tipo opcional não é nulo nem igual ao seu valor default. Caso contrário retorna false. Representa o estado "contendo alguma coisa". |
IsNone | bool | Retorna true quando o valor contido no tipo opcional é nulo ou igual ao seu valor default. Caso contrário retorna false. Representa o estado "não contendo nada". |
Construtores
Parâmetros | Retorno | Descrição |
---|---|---|
T value | Option<T> | Inicializa uma nova instância de um valor opcional de acordo com o parâmetro recebido. |
Métodos
Nome | Parâmetros | Retorno | Descrição |
---|---|---|---|
Some | T value | Option<T> | Inicializa uma nova instância de um valor opcional com o estado IsSome, caso o parâmetro recebido entre nas condições do estado IsNone é gerado um opcional neste estado. |
None | Option<T> | Inicializa uma nova instância de um valor opcional com o estado IsNone. | |
Match | Func<T, TResult> methodWhenSome Func<TResult> methodWhenNone |
TResult | Permite uma maneira de aplicar um método à um valor opcional sem necessidade de checar o estado do valor. Para isso são passados dois métodos contendo o mesmo tipo de retorno por parâmetro, um que será chamado no caso do estado IsSome e outro que será chamado no caso do estado IsNone. |
Match2 | Option<T2> option2 Func<T, T2, TResult> methodWhenSome Func<TResult> methodWhenNone |
TResult | Permite uma maneira de aplicar um método à dois valores opcionais sem necessidade de checar os estados de cada valor. Para isso são passados dois métodos contendo o mesmo tipo de retorno por parâmetro, um que será chamado no caso dos dois valores opcionais estarem no estado IsSome e outro que será chamado caso algum dos valores esteja no estado IsNone. |
Match | Action<T> actionWhenSome Action actionWhenNone |
void | Permite uma maneira de aplicar um método à um valor opcional sem necessidade de checar o estado do valor. Para isso são passados dois métodos que não retornam nada (void) por parâmetro, um que será chamado no caso do estado IsSome e outro que será chamado no caso do estado IsNone. |
Match2 | Option<T2> option2 Action<T, T2> actionWhenSome Action actionWhenNone |
void | Permite uma maneira de aplicar um método à dois valores opcionais sem necessidade de checar os estados de cada valor. Para isso são passados dois métodos que não retornam nada (void) por parâmetro, um que será chamado no caso dos dois valores opcionais estarem no estado IsSome e outro que será chamado caso algum dos valores esteja no estado IsNone. |
Sobrecargas de operadores
Operador | Parâmetros | Descrição |
---|---|---|
Cast implícito |
T value |
Permite a realização de um cast implícito de qualquer valor T para seu respectivo valor opcional.
Internamente realiza a chamada do método Some. |
Como Usar
Você pode criar um valor opcional de várias formas diferentes.
Criando valores opcionais
Você pode utilizar o construtor para criar valores contendo o estado IsSome
ou IsNone
de acordo com o parâmetro, conforme código:
Utilizando construtores
Option<int> valueWithSome = new Option<int>(10); //-> IsSome
Option<int> valueWithNone = new Option<int>(0); //-> IsNone
Você pode utilizar os métodos estáticos Some
e None
para especificar o estado desejado para o tipo opcional.
Neste caso deve-se tomar cuidado com a utilização do Some
, pois caso o valor não atenda os requisitos, mesmo utilizando este método você irá gerar um valor com o estado IsNone
.
Utilizando os métodos estáticos Some e None
Option<int> valueWithSome = Option<int>.Some(10); //-> IsSome
Option<int> valueWithNone = Option<int>.Some(0); //-> IsNone
Option<int> value2WithNone = Option<int>.None(); //-> IsNone
Por último temos a versão mais simples de todas, através do cast implícito, com isso você não precisa se preocupar com nenhum tipo de sintaxe, basta criar o valor e a linguagem fará todo o trabalho.
Utilizando cast implícito
Option<int> valueWithSome = 10; //-> IsSome
Option<int> valueWithNone = 0; //-> IsNone
Através do cast implícito implementado no tipo Option, você poderá gerar novos métodos em sua aplicação sem alterar nada no corpo especial da função, apenas indicando que a função retorna um valor opcional.
Veja este exemplo:
private Option<string> GetTextIfEven(int value)
{
if (value % 2 == 0)
return "Even";
else
return null;
}
Podemos reescrevê-lo de forma mais elegante:
private Option<string> GetTextIfEven(int value)
=> value % 2 == 0 ?
"Even"
: null;
E perceba que apenas sinalizamos que o retorno é um valor opcional. Nas instruções return
estamos retornando uma string comum.
Neste método quando o valor informado for um número par, será retornado um valor opcional no estado IsSome
contendo a string "Even"
, caso seja um valor impar, será criado um valor opcional com o estado IsNone
, desta forma não será preciso tratar o valor nulo fora deste método.
Apesar deste método funcionar corretamente, é mais indicado utilizar o método None
ao invés de null
, conforme exemplo:
private Option<string> GetTextIfEven(int value)
=> value % 2 == 0 ?
"Even"
: Option<string>.None();
Obtendo informação de um valor opcional
Para obter os valores armazenados em um valor opcional é necessário utilizar os métodos Match
ou Match2
, não há nenhuma outra forma de obter os valores.
Com isso, o programar fica impossibilitado de obter o valor armazenado em um tipo opcional sem tratar adequadamente as duas possibilidades.
Os métodos Match
esperam dois métodos por parâmetro, estes métodos podem realizar transformações no valor opcional, ou apenas retorná-los, conforme exemplos:
Utilizando Match com parâmetros nomeados
Option<int> optionalValue = 10;
int value = optionalValue.Match(
methodWhenSome: number => number,
methodWhenNone: () => 0);
Perceba que o primeiro parâmetro é o método que será executado quando o estado for IsSome
, por conta disso, este método recebe um parâmetro (number). No exemplo, o método apenas retorna este valor.
O segundo parâmetro é o método que será executado quando o estado for IsNone
, ou seja, quando não haver valor no tipo opcional. Por conta disso, este segundo método não recebe nenhum parâmetro e precisa retornar um valor do mesmo, garantindo que o programa não irá gerar erros.
Você pode omitir os nomes dos parâmetros e utilizá-los normalmente como qualquer método C#:
Utilizando Match
Option<int> optionalValue = 10;
int value = optionalValue.Match(
number => number,
() => 0);
//value = 10
Além disso, você também pode aplicar algum tipo de transformação no valor no momento de obtê-lo, como por exemplo, elevá-lo ao quadrado:
Option<int> optionalValue = 10;
int value = optionalValue.Match(
number => number * number,
() => 0);
//value = 100
Você também pode retornar o valor que precisar para o caso do estado ser IsNone
, nos exemplos anteriores foi utilizado o valor zero, mas não há nenhuma obrigatoriedade nisso.
Nos casos onde é necessário realizar uma comparação com dois valores opcionais de cada vez é necessário utilizar o método Match2
, este método funciona de maneira similar aos exemplos anteriores, mas com dois valores opcionais ao invés de somente um.
Utilizando Match2
Option<int> optionalValue = 10;
Option<int> optionalValue2 = 15;
int value = optionalValue.Match2(
optionalValue2,
(number1, number2) => number1 + number2,
() => 2);
//value = 25
Neste exemplo está sendo realizada a soma de dois valores opcionais diferentes, no caso, ambos com o estado IsSome
, fazendo com que o primeiro método seja executado:
(number1, number2) => number1 + number2
Neste método anônimo o parâmetro number1
contém o valor armazenado pela variável optinalValue
(10) e o parâmetro number2
da variável optionalValue2
(15).
Neste exemplo a variável value
receberá o valor 25.
Caso um dos valores optionais estivesse no estado IsNone
o segundo método seria disparado e o valor armazenado em value
seria 2, conforme código a seguir.
Utilizando Match2
Option<int> optionalValue = 10;
Option<int> optionalValue2 = Option<int>.None();
int value = optionalValue.Match2(
optionalValue2,
(number1, number2) => number1 + number2,
() => 2);
// value = 2
Tanto para o método Match
quanto para o método Match2
há uma sobrecarga onde os métodos não precisam retornar nenhum tipo de valor (void
).
O conceito dos valores opcionais pode ser encontrado na seção Conceitos > Valores Opcionais.