有没有更简单/更好的方法来做到这一点,因为在C#中不允许向下转换?"

时间:2012-08-09 17:47:58

标签: c# .net downcast

可能是一个争论性话题,但是......我真的很讨厌我不能做到以下几点:

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

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

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

4 个答案:

答案 0 :(得分:5)

... ERR没有。你认为这样做会发生什么,毕竟,这和你的例子一样有效:

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

毕竟,两者都继承自对象。 userUI.ImageURL会抛出异常,因为该属性不存在吗?或者是什么?这是疯狂。 :)

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

  

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

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

答案 1 :(得分:4)

如果你读到Liskov substitution principle,你会发现如果你需要向下投射,那么你的设计是有缺陷的。

答案 2 :(得分: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;}
}

然后,您只需将User添加到UserUI,而不是将User设置为UserUI

User someUser = ...;
UserUI = someUserUI = new SomeUserUI();
someUserUI.MyUser = someUser;

答案 3 :(得分:0)

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

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

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