1

可能是一个有争议的话题,但是......我真的很讨厌我不能做以下事情:

class User 
{
   public string ImageURL {get;set;}
}

class UserUI : User 
{
   public Brush ImageBrush {get;set;}
}

User user = GetFromUserFromServer(); //returns User type object, not UserUI
UserUI userUI = user;
userUI.ImageBrush = CreateBrush(userUI.ImageURL);

相反,我使用如下内容:

class User 
{
   public virtual string ImageURL {get;set;}
}

class UserUI : User 
{
   public override string ImageURL 
    {
        get
        {
            return base.ImageURL ;
        }
        set
        {
            if (value != base.ImageURL )
            {                    
                base.ImageURL = value;
                ImageBrush = CreateBrush(value);
            }
        }
    }

   public Brush ImageBrush {get;set;}

   public UserUI(User user)
   {
       ImageURL = user.ImageURL;
   }
}

User user = GetFromServer();
UserUI userUI = new UserUI(user);

它更加冗长,每当我向用户添加字段时,我都需要确保将它们复制到 UserUI 构造函数中。

公平地说,允许向下转换会使所有这一切变得更容易,更不容易出错吗?

4

4 回答 4

5

呃……不。你认为当你这样做时应该发生什么,毕竟这和你的例子一样有效:

string whatever = "";
UserUI userUI = whatever;
userUI.ImageBrush = CreateBrush(userUI.ImageURL);

毕竟,两者都继承自object。由于该属性不存在,userUI.ImageURL 是否会引发异常?要不然是啥?这太疯狂了。:)

编辑:你在上面的评论中说:

“是的。我的论点是可能应该有一种转换为派生类型的方法,并且框架会自动复制两种类型中存在的字段,并将其他字段留空。在这种情况下,ImageURL 将被复制。

如果就是你想要的,那么使用 Automapper:https ://github.com/AutoMapper/AutoMapper/wiki

于 2012-08-09T17:54:06.827 回答
4

如果您阅读了Liskov 替换原则,您会发现如果您需要向下转换,那么您的设计就有缺陷。

于 2012-08-09T17:55:37.053 回答
3

这是一个很好的例子,您应该引用“优先组合优于继承”这句话。与其让 UserUI 从 User 继承,不如让它包含一个用户:

public class UserUI
{
  public User MyUser {get; set;} //or have it set in just a constructor, if that makes more sense
  public Brush ImageBrush {get;set;}
}

然后,您不必将 a 设置User为 a ,而UserUI只需将现有的添加User到 a UserUI

User someUser = ...;
UserUI = someUserUI = new SomeUserUI();
someUserUI.MyUser = someUser;
于 2012-08-09T18:08:26.157 回答
0

如果从 GetFromServer() 返回的对象实际上是一个 UserUI 对象,那么您可以毫无问题地向下转换:

User user = GetFromServer();
UserUI userUI = (UserUI) user; // or: UserUI userUI = user as UserUI;

如果user引用实际上不是 UserUI 对象,则没有什么可向下转换的(因此转换将引发异常)。如果这是您的情况,那么您需要UserUI根据原始User对象创建一个新对象,这就是您正在做的事情,并且与向下转换完全不同。

于 2012-08-09T18:02:08.197 回答