【问题标题】:Is it bad practice to init class members with list of obj in ctor?在ctor中使用obj列表初始化类成员是不好的做法吗?
【发布时间】:2021-05-08 00:33:09
【问题描述】:
ClassName(List<object> obj) : base(obj[0])
{
   member1 = obj[1];
   ...
}

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

ClassName(int a, float b, ClassName2 c)

【问题讨论】:

  • 上述C# 语法无效。这就是现在定义构造函数的方式。请edit帖子并更正语法。
  • @JohnAlexiou 语法本身是完全有效的。
  • @TanveerBadar - 它缺少类声明。它仅在此处的许多假设下才有效。以上也是 constructor 而不是工厂模式。
  • @TanveerBadar 我展示了一个对 que 来说很重要的示例,这既不是我的代码的一部分,也不是工厂设计模式。谢谢您的评论

标签: c# oop constructor factory-pattern


【解决方案1】:

我认为您的意思是使用 List&lt;object&gt; 作为单个参数来代替每个属性的多个参数来实现构造函数。

由于 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&lt;object&gt;

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

【讨论】:

  • 谢谢,我意识到我对干净代码的意愿为其他错误和问题打开了大门,所以也许我会坚持你的“推荐方式”!
【解决方案2】:

对于提供的代码:是的。

我想说的是,这不是一个坏习惯,也不是一个意见:这是一个错误。

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

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

例如:

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 有点困扰我,除非它管理得当,因此一切都会好起来的......可以使用默认值,但这是基类,而不是子类,除非必须更改。

【讨论】:

  • 谢谢!阅读您的答案后,我现在意识到在这种情况下 - “干净的代码”(Child 的 ctor 没有获得 10 个参数)很好,但为错误输入了更多选项。
猜你喜欢
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 2019-10-23
相关资源
最近更新 更多