2013-04-05 219 views
0

我想有這種設計的:類具有相同的接口,但不同類型的屬性

public interface IDifferentTypes 
{ 
} 

public class IntegerType : IDifferentTypes 
{ 
    public int value { get; set; } 
} 

public class StringType : IDifferentTypes 
{ 
    public string value { get; set; } 
} 

public class DateTimeType : IDifferentTypes 
{ 
    public DateTime value { get; set; } 
} 

但在接口中定義的屬性「值」。

所以我可以調用類似的東西:

IDifferentTypes someInt = GetSomeInt(); // GetSomeInt() returns a IntegerType object 
Assert.AreEqual(5, someInt.value); 

IDifferentTypes someString = GetSomeString(); // GetSomeString() returns a StringType object 
Assert.AreEqual("ok", someString.value); 

問題是,值的類型是每個實施不同的,什麼是應對的最佳途徑?

回答

9

你可以定義一個通用接口(但它必須是一個屬性,或者更嚴格的,它不可能是一個字段):

public interface IHasValue<T> { 
    T Value { get; } 
} 

哪裏T是類型,一個佔位符,如果你願意,你可以這樣做:

public class HasStringValue : IHasValue<string> { 
    public string Value { get; private set; } 
} 
+1

接口無法指定字段;它將需要一個屬性 – Servy 2013-04-05 14:43:11

+0

不幸的是,你還必須在代碼中指定封閉的泛型類型,所以你不能概括一個字符串和一個int之間的接口 - 而不是沒有另一個接口可能暴露'對象'價值。 – 2013-04-05 14:44:37

+0

但是我們必須在設計時知道需要返回哪種類型? – ibiza 2013-04-05 14:44:49

5

使用泛型,如果你可以:

var someInt = GetSomeInt(); 
Assert.AreEqual(5, someInt.Value); 

var someString = GetSomeString(); 
Assert.AreEqual("ok", someString.Value); 

// ... 

public interface IDifferentTypes<T> 
{ 
    T Value { get; set; } 
} 

public class IntegerType : IDifferentTypes<int> 
{ 
    public int Value { get; set; } 
} 

public class StringType : IDifferentTypes<string> 
{ 
    public string Value { get; set; } 
} 

public class DateTimeType : IDifferentTypes<DateTime> 
{ 
    public DateTime Value { get; set; } 
} 
+0

看起來很棒!我馬上試一試。 – ibiza 2013-04-05 14:49:57

0
interface IDifferentTypes 
{ 
    Object Value { get; set; } 
} 

class StringType : IDifferentTypes 
{ 
    string _value; 

    public Object Value 
    { 
     get 
     { 
      return _value; 
     } 
     set 
     { 
      _value = value as string; 
     } 
    } 
} 

但是這意味着每次使用StringType.Value時您都需要重新進行設置。您可能還想公開一個特定類型的公共訪問器。您還可能希望添加一些防止分配錯誤類型的保護措施:

class StringType : IDifferentTypes 
{ 
    public String StringProperty { get; set; } 

    public Object Value 
    { 
     get 
     { 
      // works with any type that can auto cast to `Object` 
      return StringProperty; 
     } 
     set 
     { 
      // Optional 
      if(typeof(string) != value.GetType()) 
      { 
       throw new MyException(); 
      } 

      // works for any nullable type 
      StringProperty = value as string; 

      // OR 

      // throws an exception if conversion fails 
      StringProperty = (string)value; 
     } 
    } 
} 
+0

我不喜歡使用Value setter中的'as'運算符。它隱藏了開發人員意外地將錯誤類型設置爲屬性的情況。 – MetaFight 2013-04-05 16:18:01

+0

我不是整個設計模式的粉絲,在設置錯誤的類型時有各種問題,或者在需要訪問時需要重新設置類型。這完全取決於你如何使用它,以便通過使用(字符串)值來代替null還是獲得異常更好。 – 2013-04-05 20:34:27

+0

同意。就可維護性而言,如果使用某個類的定義或簽名不是很明顯,那麼它可能會被濫用,因此代價非常高。 – MetaFight 2013-04-08 08:13:41

相關問題