简体   繁体   中英

Classes with the same interface but different types for a property

I would like to have this kind of design :

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; }
}

but with the property 'value' defined in the interface.

So I can call something like that :

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);

Problem is that the type of value is different for each implementation, what is the best way to deal with that?

You could define a generic interface (but it will have to be a property, or, more strictly, it can't be a field):

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

Where T is the type, a placeholder, if you will, and you can do:

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

Use generics if you can:

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; }
}
interface IDifferentTypes
{
    Object Value { get; set; }
}

class StringType : IDifferentTypes
{
    string _value;

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

But this means that every time you use StringType.Value you're going to need to recast it. You may want to also expose a public accessor of the specific type. You also may want to add some protections against assigning the wrong type:

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;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM