C#:派生类上具有不同返回类型的属性

时间:2011-11-12 22:23:43

标签: c# polymorphism override abstract-class

我试图寻找这个问题的答案,但找不到太多,很可能是因为我不知道如何正确地寻找它,所以就这样吧。非常感谢所有帮助。

使用类似

的基类
abstract public class Property
{
    private String name;

    public Property(String propertyName)
    { 
        name = propertyName; 
    }

    public String Name
    {
        get { return name; }
    }

    abstract public override String ToString();
}

派生类看起来像

public class StringProperty : Property
{
    private String value; // different properties for different types

    public StringProperty(String propertyName, String value) : base(propertyName)
    {
        this.value = value;
    }

    public String Value // different signature for different properties
    {
        get { return value; }
    }

    public override String ToString()
    {
        return base.Name + ": " + value;
    }
}

在运行时,该函数接收“Property”对象的集合。我需要做些什么来获得每个的“价值”?我是否需要使用大if语句来查询每个“Property”对象的类型?如果没有,是否有更优雅的解决方案?

我试图定义一个要覆盖的抽象“Value”属性,但由于返回类型不同,所以它不起作用。我也试过玩“价值”属性,但我不能让它工作。使用类似COM的变体的想法也听起来不太合适。

提前多多感谢。

编辑:

我应该添加一些关于我要做什么的细节。属性显示在Winforms应用程序中。不同的“TextBox”表示不同的属性,并且过滤以获得适当的输入(取决于类型)。读回并存储更新的值。容器对象将被序列化为JSON并在Android和iPhone客户端上反序列化,最终这些值将传递到运行OpenGL内容的本机C ++代码的层中。我事先并不知道所有需要的属性,所以作为中间人,我想让我的代码尽可能健壮,同时能够提供OpenGL引擎。

4 个答案:

答案 0 :(得分:13)

您可以使用通用类:

public class AnyProperty<T> : Property
{
    private T value;
    // ... etc

我真的建议现在将基类作为接口:

public interface IProperty
{
    public String Name { get; }
}

public class Property<T> : IProperty
{
    public Property(String name, T value)
    {
        Name = name;
        Value = value;
    }

    public String Name { get; private set; }
    public T Value { get; private set; }

    public override String ToString()
    {
        return string.Format("{0}: {1}", Name, Value)
    }
}

以下是示例用法:

var intProp = new Property<int>       ("age", 32);    
var strProp = new Property<string>    ("name", "Earl");    
var enumProp = new Property<ColorEnum> ("eye color", ColorEnum.Magenta);    

为了使构造更简单,您可以使用工厂方法:

public static Property<T> MakeProperty(string name, T value)
{
    return new Property<T>(name,value);
}

var intProp = MakeProperty("age", 32);    
var strProp = MakeProperty("name", "Earl");    
var enumProp = MakeProperty("eye color", ColorEnum.Magenta);    

<子> 不一定推荐,有点OT:

你可以使用扩展方法让它变得更加有趣:

public static Property<T> AsProp<T>(this T value, string name)
{
    return new Property<T>(name,value);
}

var intProp = 32.AsProp("age");
var strProp = "Earl".AsProp("name");
var enumProp = ColorEnum.Magenta.AsProp("eye color");

答案 1 :(得分:3)

您只需使用object类型即可。你想达到什么目的?这里的问题不是类的结构,而是接收Property个对象集合的函数。甚至不可能将某些内容转换为未知类型,因为您不知道需要存储哪种类型的变量。

基本上,您的Property.Value属性必须是object类型。在使用Property对象的方法中,您需要对它们执行某些操作,而您正在执行的操作将决定它应该如何构建。你打印价值了吗?让*Value类继承自抽象PropertyValue类并覆盖ToString()以返回适当的字符串表示。

答案 2 :(得分:2)

我对您的示例代码进行了一些更改并获得了此结果...

   abstract public class Property
    {
        private readonly String _name;
        public Property(String propertyName)
        {
            _name = propertyName;
        }
        public String Name
        {
            get { return _name; }
        }
        abstract public override String ToString();
    }
    public class StringProperty : Property
    {
        private readonly dynamic _value; // different properties for different types 
        public StringProperty(String propertyName, dynamic value)
            : base(propertyName)
        {
            this._value = value;
        }
        public dynamic Value // different signature for different properties 
        {
            get { return _value; }
        }
        public override String ToString()
        {
            return base.Name + ": " + _value;
        }
    }
    static void Main(string[] args)
    {
        StringProperty sp = new StringProperty("A double", 3.444);
        StringProperty sp2 = new StringProperty("My int", 4343);
        StringProperty sp3 = new StringProperty("My directory", new  DirectoryInfo("Some directory"));
        StringProperty sp4 = new StringProperty("My null", null);
        Console.WriteLine(sp);
        Console.WriteLine(sp2);
        Console.WriteLine(sp3);
        Console.WriteLine(sp4);
    }
}

以预期的方式将值正确打印到控制台。

答案 3 :(得分:2)

这需要重新考虑一下,但您是否考虑使用动态类型(在.net4中引入)

并没有真正解决你的问题,而是侧重于它。 您的属性可以基本上只是一个

Dictionary<String, dynamic>

,问题是它们直到运行时才被评估,所以你没有编译器支持输入。

所以你想要的 int SomeValue = MyProperties [SomePropertyName] + 10;

所以如果 MyProperties [SomePropertyName] = 10; //一切都很好

如果是76.52或Fred,则添加将在执行时抛出异常。

代码更简单,更清晰,没有额外的铸造,所需的脚手架数量很少,但是,你需要对广泛和宗教地使用字典的代码进行单元测试。