在c#中将值类型更改为引用类型的最佳方法是什么?

本文关键字:引用类型 最佳 方法 是什么 类型 | 更新日期: 2023-09-27 18:05:22

我定义了三个类,如下所示:

public class Base
{
    public int Id { get; set; }
}
public class Bar : Base { ... }
public class Foo : Base
{
    public int? ParentId { get; set; }
    public Base Parent { get; set; }
    public int? FooParentId { get; set; }
    public Foo FooParent { get; set; }
    public int? BarParentId { get; set; }
    public Bar BarParent { get; set; }
    public Foo(Foo parent)
    {
        FooParent = parent;
        FooParentId = parent.Id;
        Parent = FooParent; // Now changes to Parent are reflected on FooParent
        ParentId = FooParentId; // Changes to ParentId are not reflected because it is a value type.
    }
    public Foo(Bar parent)
    {
        // Same implementation as ctor(Foo parent);
    }
}

我想做的是让Parent参考FooParentBarParent(我认为这相当简单,),然后让ParentId参考FooParentIdBarParentId。使ParentId成为引用类型的最合理的方法是什么?

这里的答案提到整数的装箱/拆箱有很多与之相关的问题。
这真的是一个糟糕的解决方案吗?

编辑:


我应该提到FooBar是实体框架表。Foo是一个对象,可以是一个表的子对象,也可以是另一个表的子对象,为了使实体框架代码首先正确生成表,必须同时定义FooParentBarParent。同样,ParentId也不能在它的getter中引用Parent。实体框架也应该为此负责。实体框架在调用context.Set<Foo>().Add(newItem);时重新插入现有对象。

在c#中将值类型更改为引用类型的最佳方法是什么?

如果您被EF所束缚,您可以使用委托来传播基于在构造函数中传递的类型的ParentId的更改。我不知道EF会不会抱怨。

例如,使用Action<T>委托,我们可以将对ParentId的更改转发给相应的[Foo|Bar]ParentId:

public class Base
{
    public int Id { get; set; }
}
public class Bar : Base {  }
public class Foo : Base
{
    private int? _parentId;
    public int? ParentId { 
        get{ return _parentId; } 
        set{ 
            _parentId = value;
            if( OnParentChangeAction != null ) {
                OnParentChangeAction( _parentId ); 
            }
        } 
    }
    public Base Parent { get; set; }
    public int? FooParentId { get; set; }
    public Foo FooParent { get; set; }
    public int? BarParentId { get; set; }
    public Bar BarParent { get; set; }
    private Action<int?> OnParentChangeAction{ get; set; }
    public Foo(Foo parent)
    {
        FooParent = parent;
        FooParentId = parent.Id;
        Parent = FooParent;
        ParentId = FooParentId;
        OnParentChangeAction = newParentId => FooParentId = newParentId;
    }
    public Foo(Bar parent)
    {
        BarParent = parent;
        BarParentId = parent.Id;
        Parent = BarParent; 
        ParentId = BarParentId; 
        OnParentChangeAction = newParentId => BarParentId = newParentId;
    }
}

由于您已经有了父对象的引用,您可以使用属性获得它的Id:

    public int? ParentId 
    { 
        get
        {
            return Parent != null ? Parent.Id : null;
        }
    }

您可以在FooParentIdBarParentId属性的getset访问器中添加逻辑,但同意@Servy认为这是一个糟糕的设计。

原因甚至不仅仅是同时拥有id和对对象的引用。我不明白为什么你需要有BarParent和foparent,只是有一个类型为IParent的属性,然后使用这个接口提供的方法利用继承和多态性的所有好处与它通信。