2009-02-09 23 views

cevap

64

Unboxing yalnızca tür aynıysa çalışır! Hedef değeri içermeyen bir object kutusunun işaretini kaldıramazsınız. Ne gerek

Bu değer, bir decimal olarak çözümlenebilir olup olmadığını bakar
decimal tmpvalue; 
decimal? result = decimal.TryParse((string)value, out tmpvalue) ? 
        tmpvalue : (decimal?)null; 

çizgisinde bir şeydir. Evet ise, o zaman result; başka null atayın. Aşağıdaki kod yaklaşık aynı yapar ve koşullu operatör ?: aşina olmayan insanlar için anlaşılması kolay olabilir:

decimal tmpvalue; 
decimal? result = null; 
if (decimal.TryParse((string)value, out tmpvalue)) 
    result = tmpvalue; 
+2

Burada "özdeş" kelimesini kullanmazdım.Örneğin, enum türleri ile bunların altta yatan türü olan T ve T? Ve diğer bazı garip durum IIRC arasında kutucuğu kaldırabilirsiniz. CLR beklediğinizden daha fazla izin veriyor. –

+0

(Ama evet, bir dizgeyi ayrıştırmak için kutudan çıkarmayı beklememelisiniz :) –

+0

@Jon: Daha iyi bir formülasyonunuz var mı? Bunun eksikliğiyle, yorumunuzu cevabım içine kopyalayacağım çünkü bu uyarıyı güzel bir şekilde ifade ediyor. –

2

ve decimal? temp = (decimal?)value;

+0

çalışmıyor. Nedenini açıklayamıyorum. Hata ayıklamada, Visual Studio sökme işlemini göstermek istiyor ... – Natrium

+1

Bu çok garip çünkü benim tarafımda iyi çalışıyor ..... – StevenMcD

+0

Değer bir dize örneğini tutuyorsa işe yaramaz. Ondalık bir örneğini tutarsa ​​çalışması gerekir. – pauloya

5

kullanırsanız ondalık ayrıştırmak gerekir. dize doğru değil ne zaman ondalık boş olmasını istiyorsanız, TryParse kullanın:

decimal parsedValue; 
decimal? temp = decimal.TryParse(value, out parsedValue) 
       ? value 
       : (decimal?)null; 

hasta formated dizeleri ayrıştırma sırasında durumları önlemek olacaktır Bu şekilde.

Neredeyse tüm ilkel türler, dizeden dönüştürmek için bir Parse ve TryParse yöntemleri sağlar.

Ayrıca ondalık ayırıcıyla ilgili sorunları önlemek için yönteme sağlayıcı argümanı için bir kültür iletilmesi önerilir. Başka bir sistemden okuyorsanız, CultureInfo.InvariantCulture muhtemelen gitmek için bir yoldur (ancak varsayılan değil). Eğer dizeleri ayrıştırmak, ama ya null, bir decimal veya null decimal almasını sağlamak istiyorum istemiyorsanız

bool TryParse(string s, NumberStyles style, 
    IFormatProvider provider, out decimal result) 
+0

hatasını atar (niçin?) Null değerini unutmuştum ... pardon ama kültür kısmı hala önemli. – thinkbeforecoding

+3

Bu cevap, 'temp' değerine 'değer' atamak işe yaramadığından hatalı. Olmalı ? parsedValue: (ondalık?) null; – offner

1

, o zaman böyle bir şey yapabileceğini:

public static Nullable<T> Convert<T>(object input) 
    where T : struct 
{ 
    if (input == null) 
     return null; 
    if (input is Nullable<T> || input is T) 
     return (Nullable<T>)input; 
    throw new InvalidCastException(); 
} 

Yapabilirsin istisnaları önlemek istemiyorsanız, bunun yerine gerçek boş değerler ile kötü oyuncular arasında ayrım yapmasa da, son satırda null değerini döndürür.

"as" işleci, "as" işlecinin değer türleri üzerinde çalışmadığından ve denetimsiz bir InvalidCastException atılmış olabileceğinden "is" operatörünü kullanmanız gerektiğini unutmayın.

Ayrıca o bir uzantısı yöntemi yapabiliriz:

public static class ObjectExtensions 
{ 
    public static Nullable<T> ToNullable<T>(this object input) 
     where T : struct 
    { 
     if (input == null) 
      return null; 
     if (input is Nullable<T> || input is T) 
      return (Nullable<T>)input; 
     throw new InvalidCastException(); 
    } 
} 

Ve bu gibi kullanmak:

object value = 123.45m; 
decimal? dec = value.ToNullable<decimal>(); 

Bu kutudan çıkarma boş başvurular hakkında kod sözleşme uyarıları önlemeye yardımcı olacaktır.

+0

Uzantı yönteminizi test ettiniz mi? Denedim ve NullReferenceException var null ondalık – Shiva

+0

@Shiva dönüştürülecek geçerli bir çift değeri için var. İlk satırda belirtildiği gibi uzantısı yöntemi, çiftler için tasarlanmamıştır: "ya null, bir ondalık alıyorsunuz veya null bir ondalık " –