是否可以在C#中更改对象类型

时间:2014-04-16 13:56:38

标签: c# .net object types

我遇到了一些问题,以满足客户的要求。

我会尽量保持这个例子非常简单,只是想一想这个问题,希望能找到解决方案。

此时我们有一个" Shape"例如,形状有一些特殊,可以是方形,三角形等。

到目前为止一切顺利,一切都很好。

现在由于某种原因,我的客户想要将系统中已存在的方块更改为三角形,但保留所有数据的形状。

可能吗?有什么办法吗?

7 个答案:

答案 0 :(得分:4)

您无法更改对象的运行时类型。只需创建一个新的三角形,复制所有相关值并扔掉正方形。如果广场已被许多其他对象引用,这当然会变得棘手,因为您将不得不更新所有引用。

如果不能替换对象,则可能需要提供一个可以作为任何形状的通用形状类。例如,这个类可以是一个具体形状类的实例周围的薄包装器。这使您可以用新的三角形替换包装的正方形,而外部世界可以保留对包装类的所有引用。

答案 1 :(得分:1)

在不创建所需类型的新对象并手动更新所有引用(非常容易出错)的情况下,无法替换现有对象的类型 - 我会考虑一种解决方法。

设计方面,如果"类型" (在行为意义上,不是静态类型系统中的实际类型)需要灵活,问题可以通过委托来解决。对象本身将保持不变,但交换代表。

答案 2 :(得分:1)

您无法更改类型,但您可以使用适当的设计解决此问题。 如果想法是每个对象都是一个Shape并且它具有必须可替换的附加信息,那么将它作为一个单独的成员保留是有意义的。例如(伪):

public class ShapeContainer 
{
 public int x { get; set; }
 public int y { get; set; }

 public ISpecificShape SpecificShape { get; set; }
}

public class Triangle : ISpecificShape 
{
// ...
// ...
}

public class Rectange : ISpecificShape 
{
// ...
// ...
}

这样,您可以更改特定形状。

如果要对其进行输入,可以将以下通用Get函数添加到Shape:

GetSpecificShape<T>() where T : ISpecificShape 
{
 return (T)this.SpecificShape;
}

如果数据类型不匹配但符合您的设计要求,则会引发异常。

您怎么看?

答案 3 :(得分:0)

您需要的是被称为继承。

这是一个模型:

创建一个StrokeStyle类

  • 宽度
  • 颜色
  • 类型(虚线,实线)

创建一个FillStyle类

  • 颜色
  • 类型(实体,渐变)

创建一个具有strokeStyle和fillStyle属性的VectorShape类(每个属性都是类的实例)。

创建Square和Triangle类,两者都继承了VectorShape类。他们将共享VectorShape属性。您必须用新的Triangle实例替换方形实例,并复制要保留的属性。

你也可以用一个shapetype属性做一个类,它将是“正方形”或“三角形”......然后你就可以在不更换对象的情况下改变类型。但是你必须在所有方法中处理shapetype,即:computeArea()。这将导致一个令人难以理解的代码。这是可能的,但这是不好的方式。

答案 4 :(得分:-2)

您可以在数据类型之间进行转换。结果可以放在一个新对象中。原始对象的类型不会更改。但通常只有在这样做时才提供这种机制。在将正方形转换为三角形的情况下,我看不出这是有意义的,但也许有一些关于你的特定应用的地方有意义(即,将正方形转换为具有相同尺寸周长或面积的三角形)。

有关在不同类型之间进行转换的示例,请参阅MSDN上的Using Conversion Operators

来自MSDN上的Casting and Type Conversions

  

因为C#在编译时是静态类型的,所以在变量之后   声明,它不能再次声明或用于存储值   另一种类型,除非该类型可转换为变量的类型。   例如,没有从整数到任意的转换   串。因此,在将i声明为整数后,则不能   为其分配字符串“Hello”,如下面的代码所示。

答案 5 :(得分:-2)

Clone()课程中定义并实施虚拟Shape方法。你有两个&#34;合理的&#34;选项。无论您选择哪种实施方式,您都无法发明&#34;发明&#34;不存在的数据 - 正方形有一个边长,三角形有3个。

第一个选项是手动复制所有字段:

class Shape{

  public virtual Shape Clone(Shape target = null){
    if (target == null) target = new Shape();
    target.Prop1 = this.Prop1;
    return target;
  } 
}

class Square{
  public override Shape Clone(Shape target = null){
    if (target == null) target = new Square();
    base.Clone(target);
    if (target.GetType() == typeof(Square)){
      target.PropSquare1 = this.PropSquare1; // some casting etc
    }
  } 
}

//更改类型:    var triangle = new Triangle();    square.Clone(三角形);

第二个选项,我更喜欢在性能方面进行交易以方便使用。它是使用序列化程序将形状序列化为一种形式并反序列化为另一种形状。您可能需要处理中间的序列化结果。以下是伪代码版本:

class Shape{
  public virtual T Clone<T>() where T: Shape{
    var data = JsonConvert.Serialize(this);
    data = data.Replace("Square","Triangle");
    return JsonConvert.Deserialize<T>(data);
  }
}

答案 6 :(得分:-2)

有一个Convert.ChangeType(dObject,typeof(SomeClass));

但是为了转换成功,值必须实现IConvertible接口,因为该方法只是调用适当的IConvertible方法。该方法要求支持将值转换为conversionType。