# Either ### Jak używać Either umożliwa nam zwrócenie z metody bądź nawet kontrolera, dwóch możliwych wyników. Dla ułatwienia zrozumienai poniżej podaję przykłady stosowania. Jako typ zmiennej zwracanej z api: W tym przypadku wskazujemy, że nasze api zwróci albo CharacterViewModel albo ErrorResponse ```cs public async Task> Get(int id) ``` Aby zwrócić ten typ mamy dwie możliwości. Możemy wywołać metodę z serisu, która ma nam zwrócić CharacterViewModel. Następnie sprawdzić czy otrzymana wartość CharacerViewModel zawiera jakiekolwiek dane i odpowiednio, jeśli tak to zwracamy otrzymany viewmodel a jeśli nie tworzymy ErrorResponse i zwracamy wynik: ```cs public async Task> Get(int id) { Either result = await _service.Get(id); if (result.Left != null) { return result; } else { result = new ErrorResponse { StatusCode = 400, Message = "Coś poszło nie tak" }; return result; } } ``` W przypadku jesli serwis nie znajdzie wartości otrzymamy: ```json { "left":null, "right":{ "statusCode":400, "message":"Coś poszło nie tak"}, "isLeft":false} ``` Drugim sposobem jest zmiana działania serwisu: ```cs public async Task> GetCharacter(int id) { var repoResult = await this.Repository.Get(id); if (repoResult != null) { return Mapper.Map(repoResult); } else { return new ErrorResponse() { StatusCode = 404, Message = "Coś poszło nie tak" }; } } ``` Wtedy kontroler wygląda tak : ```sh public async Task> Get(int id) { return await this._service.GetCharacter(id); } ``` ### Przypisanie nowej wartości Jeśli z jakiegośpowodu będziemy chcieli zmienić wartość obiektu Either, musimy dokonać tego w taki oto sposób: ```cs UserViewModel user = new UserViewModel() { Id = 1, Username = "Testowy", Password = "Secret" }; Either test = "asd"; // zmieniamy wartość Either test = user; // Warto zauważyć, że możemy zmienić wartość obiektu znajdujacego się wewnątrz // którejś ze zmiennej o ile jest on publiczny test.Left.Username = "test"; // Jednak jeśli dokonamy tego po zmianie wartości obietu na inny pomimo tego, że // dla kodu jest to ok, to nie zadziała to poprawnie, ponieważ wartość starego obiektu // jest zmieniana na null(dla boola na false) test = "asd"; test.Left.Username = "błąd"; ``` ### LeftOrDefault() oraz RightOrDefault() Zwracają one wartość wybranej zmiennej bądź jej wartość defaultową. Dla wiekszości obiektów jest to null, wyjatkiem jest tutaj bool, który zwróci nam false. ```cs var test = (Either)true; var a = test.LeftOrDefault(); // zwróci nam true var b = test.RightOrDefault(); // zwróci nam null test = "asd"; var c = test.LeftOrDefault(); // zwróci nam false var d = test.RightOrDefault(); // zwróci nam "asd" ``` ### Match Funkcja ta pozwala nam na odpalenie odpowiedniej metody w zależności od tego jako typ zmiennej jest aktualnie przechowywany w obiekcie Either. Niestety ograniczeniem jest to, ze obie funkcje musza docelowo zwrócić ten sam typ. ```cs // ładujemy userviewmodel do obiektu Either i wywoływamy matcha pdając dwie funkcje test = user; // zwwrócny zostanie string "Test1" test.Match(this.Test1, this.Test2); // ładujemy stringa do obiektu Either i wywoływamy matcha pdając dwie funkcje test = "asd"; // zwwrócny zostanie string "Test2" test.Match(this.Test1, this.Test2); public string Test1(UserViewModel viewModel) { return "Test1"; } public string Test2(string text) { return "Test2"; } ``` Warto zauważyć, że możemy wykorzystać tutaj lambde by rozszerzyć nasze możliwości: ```cs test = "asd"; test.Match( Test1, second => { int z = Test2(second); // tutaj możemy robić już co nam się tylko podoba // pamiętać należy ze finalnie musimy coś zwrócić // chyba, że nasze obie funkcje są typu void return z.ToString(); }); public string Test1(UserViewModel viewModel) { return "Test1"; } public int Test2(string text) { return 12; } ``` Możemy też podać jedna funkcję typu void a drugą typu innego np. string albo int: ```cs y = ""; test = "asd"; test.Match( Test1, second => { var x = this.Test2(second); //jednak nie ma możliwości zwrócenia wartości // możemy za to zwrócić wyniki do zewnętrznej zmiennej y = x; }); public void Test1(UserViewModel viewModel) { //...coś robi } public string Test2(string text) { return "Test2"; } ```