2013-04-05 152 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

相关问题