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

本文关键字:返回类型 属性 派生 | 更新日期: 2023-09-27 18:14:39

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

与看起来像

的基类
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语句来查询每个"属性"对象的类型?如果没有,是否有更优雅的解决方案?

我试图定义一个抽象的"值"属性被覆盖,但由于返回类型不同,它没有工作。我也试着玩阴影的"值"属性,但我不能使它工作。使用类似com的变体的想法听起来也不太合适。

提前谢谢你。

编辑:

我应该详细说明我要做的事情。不同的"文本框"代表不同的属性,并过滤正确的输入(取决于类型)。更新后的值被回读并存储。容器对象将被序列化为JSON,并在Android和iPhone客户端上反序列化,最终这些值将被传递到运行本地c++代码的层中,执行OpenGL操作。我事先不知道所有需要的属性,所以作为中间人,我想让我的代码尽可能健壮,同时能够提供OpenGL引擎。

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

你可以使用一个泛型类:

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

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

所以基本上,你的Property.Value属性需要类型为object。在使用Property对象的方法中,您需要使用它们做一些事情,并且您正在做的事情将决定它应该如何结构化。您正在打印值吗?从抽象PropertyValue类继承*Value类并重写ToString()以返回适当的字符串表示

我对您的示例代码进行了一些更改,并得到了这个结果…

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

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

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

并不能真正解决你的问题,只是在回避它。属性可以是

Dictionary<String, dynamic>

,问题是它们直到运行时才被计算,所以编译器不支持键入

so given you wantint SomeValue = MyProperties[SomePropertyName] + 10;

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

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

代码更简单、更干净,不需要额外的强制转换,所需的脚手架数量也很少,但是,您需要对广泛和虔诚地使用字典的代码进行单元测试。