1

我有这样的课:

public class ItemField
{

    public string FieldName { get; set; }

    public object FieldValue
    {
        get;
        set;
    }
}

我想拥有它,以便“FieldValue”只能是字符串、MyItem 或 List<MyItem> 类型。我也希望它在代码使用此类时,访问“FieldValue”返回正确类型的对象。有没有办法做到这一点?我对泛型不太清楚,但似乎有一种方法可以使用它来做到这一点......

4

5 回答 5

2

一个属性只能返回一种特定的类型,你不能让它根据字段值的实际类型返回不同的数据类型。

您可以对类使用泛型,但是您需要为要存储在其中的数据类型创建类实例:

public class ItemField<T> {

  public string FieldName { get; set; }

  public T FieldValue {
    get;
    set;
  }

}
于 2012-09-20T19:38:31.123 回答
2

假设客户端确切地知道它获取的字段类型,您可以将属性定义更改为使用泛型的函数,如下所示:

private object fieldValue;

public T GetFieldValue<T>() {
    return (T)fieldValue;
}

用户必须像这样调用这个方法:

MyItem item = itemField.GetFieldValue<MyItem>();

但是,转换仍然存在,并且不清楚用户应该如何知道提供什么类型作为泛型类型参数。

更好的方法是使用某种双重调度机制,例如访问者模式,来“反转”方向并让您的字段将值“推送”到调用者中。

interface IItemFieldVisitor {
    void VisitString(string val);
    void VisitMyItem(MyItem val);
    void VisitList(IList<MyItem> val);
}

interface IItemField {
    string Name {get;set;}
    void Accept(IItemFieldVisitor visitor);
}

class StringItemField : IItemField {
    public string Name {get;set;}
    private string val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitString(val);
    }
}

class MyItemItemField : IItemField {
    public string Name {get;set;}
    private MyItem val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitMyItem(val);
    }
}

class MyItemListItemField : IItemField {
    public string Name {get;set;}
    private IList<MyItem> val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitList(val);
    }
}

现在您可以创建IItemFieldVisitor接口实例,并将它们传递给IItemField对象。访问者将收到具有特定值的回调,而无需知道IItemField被访问对象的类型。

于 2012-09-20T19:38:52.720 回答
1

您可以创建自己的抽象类“字段”并从抽象类派生一个字符串、MyItem 或 List。http://www.techotopia.com/index.php/Understanding_C_Sharp_Abstract_Classes

您可以在此链接查看抽象类工厂:http: //dotnetslackers.com/articles/designpatterns/Design-Patterns-Part-3.aspx

于 2012-09-20T19:43:48.390 回答
1

因此,您似乎不确定是否应该退回一件物品或一组物品。与其动态更改返回类型(这是您实际上无法以有用的方式做的事情),不如始终返回一个集合更有意义。如果合适,该集合始终可以包含单个项目。

如果您将返回类型更改为,List<MyItem>那么大多数问题和不良代码气味都会消失。

于 2012-09-20T19:59:58.493 回答
1

如您所知string,不用作通用约束,请查看MSDN

public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>

因此,如果您将 T 约束为字符串,则可以像这样解决

public class ItemField<T> where T :  ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
{
    public string FieldName { get; set; }
    public T FieldValue { get; set; }

}
于 2012-09-21T07:10:14.163 回答