20 Mayıs 2016 Cuma

Nullable ve Optional

Giriş
Nullable C# ile gelen bir kavram. Bir değişkenin, primitive bile olse, hem gerçek bir değer alabileceğini hem de değeri belirtilmemiş olabileceğini gösteriyor.

Optional ise Nullable ile çok benzer. Primitive tipler yerine nesneler için kullanılıyor.

Nullable ve Girdi Parametresi
Optional bir tipi girdi parametresi olarak kullanmak bazıları tarafından tavsiye edilmiyor. Bu kişiler Optional daha çok döndürülen tip olarak kullanılmalı tezini savunuyorlar.

Guava
Örnek:
Optional<Book> optionalBook = findBook(id);
if (optionalBook.isPresent()) {
    Book book = optionalBook.get();
  }

STL Optional
STL Optional daha standarda girmedi. Ancak yine de nasıl kullanılacağını yazmak istedim. Şimdilik boost optional'ı kullanmak gerekir.

value metodu
Örnek. bool converter ile optional nesnesinin dolu olduğu kontrol edilir. Eğer bu kontrol yapılmazsa value() metodu bad_optional_access exception'ı atar.

if (o)  // redundant check
  f(o.value())

bool converter
Optional sınıfının dolu olup olmadığını anlamak için kullanılır. Örnek: Burada std::optional sınıfının * operatörü ile kullanıldığına dikkat etmek gerekir.
if (o)
  f(*o)
boost optional
boost optional yazısına taşıdım.

Java
ofNullable ve Stream
Optional sınıfının en önemli özelliği ofNullable ile verilen nesneyi sarmalamasıdır. Böylece Java 8 ile gelen stream sınıfları ile rahatlıkla kullanılabilir.
<T> Stream<T> getStream(List<T> list) {
    return Optional.ofNullable(list).map(List::stream).orElseGet(Stream::empty);
}
Bir başka örnekte elimizde şöyle sınıflar olsun
Class A {
    String a1;
}
Class B {
    Optional<A> a;
}
Class C {
    Optional<B> b;
}
Class D {
    Optional<C> c;
}
C'den B'yi. B'den A'yı alana bir zincir kuralım. A değerini veya arada herhangi bir nesne null ise null değerin elde etmek için şöyle yaparız.
String getAValue(D d) {
   return Optional.ofNullable(d)
       .map(D::getC).map(C::getB).map(B::getA).map(A::getA1).orElse(null);
}

C#
C#'ta nesneler tanımlanırken soru işaret ile nullable yapılabilir. Nullable aslında aşağıdaki struct'a benziyor. where T : struct kısıtı yüzüden nullable sadece value type'lar ile kullanılabilir.

public struct Nullable<T> where T : struct
{
    private T value;
    private bool hasValue;
}
Basit bir nullable kullanımı
int? myInt = null;
var hasValue = myInt.HasValue;//false
Bir başka örnek string'e çevrim
string x = null;
x.ToString(); // throws a NullReferenceException

int? y = null;
y.ToString(); // returns ""

Nullable tipler C#'taki Null Coalescing Operator ile de sıkça beraber kullanılırlar.
Örnek:
Type? v = x?.y?.z; 
if (v.HasValue) {
    var value = v.GetValueOrDefault();     
    // code using value 
} 
Lifted Operator for Arithmetic Operations
Nullable tiplere ++, +, --, -, ! ve ~ operatörlerinin uygulanmasını sağlar. Eğe nesne null ise bu özel operatörler null döner.
int? a = null;
a++; // No NullReferenceException
Console.WriteLine(a); // Empty line
Lifted Operator for Conversion
Açıklaması şöyle

6.4.2 Lifted conversion operators
Given a user-defined conversion operator that converts from a non-nullable value type S to a non-nullable value type T, a lifted conversion operator exists that converts from S? to T?. This lifted conversion operator performs an unwrapping from S? to S followed by the user-defined conversion from S to T followed by a wrapping from T to T?, except that a null valued S? converts directly to a null valued T?.

Kod olarak şöyle kullanıyoruz. nullable decimal alan bir metodumuz olsun.
public static string PrintDecimal(decimal? input, string NumberFormat = null){ }
Bu metodu nullable int ile çağırabiliriz.
int? MaxFaltas = 0;
Label.Text = CustomConvert.PrintDecimal(MaxFaltas);








Hiç yorum yok:

Yorum Gönder