在 ctor 中使用 obj 列表初始化类成员是不好的做法吗?

时间:2021-05-08 00:33:09

标签: c# oop constructor factory-pattern

ClassName(List<object> obj) : base(obj[0])
{
   member1 = obj[1];
   ...
}

我在 oop C# 中有一个作业。我已经实现了一个工厂设计模式,我正在初始化的类是在运行时确定的。此外,由于用户输入,obj 列表正在发生变化。以这种方式初始化类成员是否比在 ctor 处获取所有特定参数的经典方式更糟糕或最佳实践,例如:

ClassName(int a, float b, ClassName2 c)

2 个答案:

答案 0 :(得分:0)

对于提供的代码:是的。

我还要说,这不是一种坏习惯,也不是一种意见:这是一个错误。

因为如果列表为空或为空,你会得到一个异常。

你必须在构造函数中检查边界并做不同的事情。

例如:

class BaseClass
{
  protected void Initialize(object instance)
  {
    ...
  }
  public BaseClass(object instance)
  {
    Initialize(instance);
  }
}

class ChildClass : BaseClass
{
  ChildClass(List<object> items)
  {
    if ( items.Count > 0 ) Initialize(items[0]);
    if ( items.Count > 1 ) member1 = items[1];
    ...
  }
}

也许您可以在此映射表上使用属性集合(数组、列表...)和循环。

当然你也可以写这样的东西:

ChildClass(List<object> items) : base(items != null && items.Count > 0 ? items[0] : null)

但原则上,在不了解更多代码和规范的情况下,null 有点困扰我,除非它管理得当,因此一切都会好起来的……可以使用默认值,但这是基类的角色,而不是子类,除非必须更改。

答案 1 :(得分:0)

我认为您的意思是使用 List<object> 作为单个参数而不是每个属性的多个参数来实现构造函数。

由于 c# 类型安全,不建议这样做。不仅从各种类型转换到 object 并再次返回是危险的,而且速度也很慢,并且会引入难以发现的细微错误。

推荐方式

public abstract class BaseClass
{
    protected BaseClass(string baseName)
    {
        this.BaseName=baseName;
    }

    public string BaseName { get; }    
}

public class DerivedClass : BaseClass
{
    public DerivedClass(string baseName, int iD) 
        : base(baseName)
    {
        this.ID=iD;
    }

    public int ID { get; }
}

不太推荐的方式

使用params object[]

    public DerivedClass(params object[] args)
        : base( args[0] as string)
    {
        this.ID = (int)args[1];
    }

使用List<object>

    public DerivedClass(List<object> args)
        : base( args[0] as string)
    {
        this.ID = (int)args[1];
    }

替代类型安全方式

您也可以使用 ValueTuple 来携带参数

    public DerivedClass((string baseName, int id) args)
        : base( args.baseName)
    {
        this.ID = args.id;
    }