我正在尝试将一些代码从delphi移植到c中,我发现了一个无法以合理的方式实现的构造,同时遵守了.net框架设计指南(我在问题的最后解决了这个问题)。
很明显,C++、Java、C++(以及许多其他语言)提供了方法/构造函数重载的含义,但是Delphi构造函数还可以有多个名称。这样就可以编写直接表示意图的代码:

var
  Data, ParI, ParD, Locl: TDataElement;
begin
  Data := TDataElement.Create('Element');
  ParI := TDataElement.CreateParam('IntElement', 22);
  ParD := TDataElement.CreateParam('DblElement', 3.14);
  Locl := TDataElement.CreateLocal('LocalElement');
  // ... use the above objects ...
end;

简化代码如下:
unit DataManager;

interface

TDataElement = class
  FName: string;
  FPersistent: Boolean;
public
  constructor Create(AName: string);
  constructor CreateParam(AName: string; DefaultInt: Integer); overload;
  constructor CreateParam(AName: string; DefaultDouble: Double); overload;
  constructor CreateLocal(AName: string);
  property Name: string read FName;;
  property Persistent: Boolean read FPersistent;
end;

implementation

constructor TDataElement.Create(AName: string);
begin
  FName := AName;
  FPersistent := True;
  // ... other initialization ...
end;

constructor TDataElement.CreateParam(AName: string; DefaultDouble: Double);
begin
  Create(AName);
  // ... use DefaultInt ...
end;

constructor TDataElement.CreateParam(AName: string; DefaultInt: Integer);
begin
  Create(AName);
  // ... use DefaultDouble...
end;

constructor TDataElement.CreateLocal(AName: string);
begin
  Create(AName);
  FPersistent := False;
  // ... other code for local (non-persistent) elements ...
end;

特别是在c构造函数中,必须与类具有相同的名称,因此我首先尝试用枚举区分行为。唉,我偶然发现了几个问题:
每个构造函数中的第一个参数是同一类型(ElementKind)
构造器不像在delphi中那样容易识别(create vs.createparam vs.createlocal)
在dataelement的子类中需要格外小心
可能出错,例如指定elementKind.doubleparam并传递整数值
处理本地元素需要额外的bool参数
第一次尝试如下:
public enum ElementKind
{
    Regular, IntParam, DoubleParam, Local
}

public class DataElement
{
    private string FName;
    public string Name { get { return FName; } }

    private bool FPersistent;
    public bool Persistent { get { return FPersistent; } }

    public DataElement(ElementKind kind, string name)
    {
        FName = name;
        // ugly switch :-(
        switch (kind)
        {
            case ElementKind.Regular:
            case ElementKind.IntParam:
            case ElementKind.DoubleParam:
                FPersistent = true;
                break;
            case ElementKind.Local:
                FPersistent = false;
                break;
        }
        // ... other initialization ...
    }

    public DataElement(ElementKind kind, string name, int defaultInt)
        : this(kind, name)
    {
        // ... use defaultInt ...
    }

    public DataElement(ElementKind kind, string name, double defaultDouble)
        : this(kind, name)
    {
        // ... use defaultDouble ...
    }

    // Redundant "bool local" parameter :-(
    public DataElement(ElementKind kind, string name, bool local)
        : this(kind, name)
    {
        // What to do when "local" is false ???

        // ... other code for local (non-persistent) elements ...
    }
}

public class Program
{
    public void Run()
    {
        DataElement data = new DataElement(ElementKind.Regular, "Element");
        DataElement parI = new DataElement(ElementKind.IntParam, "IntElement", 22);
        DataElement parD = new DataElement(ElementKind.DoubleParam, "DblElement", 3.14);
        DataElement locl = new DataElement(ElementKind.Local, "LocalElement");
    }
}

然后我尝试了更多面向对象的方法来按类型区分构造函数,同时在run()方法中保持相同的初始化代码:
public class ElementKind
{
    public class RegularElement
    {
        internal RegularElement() { /* disallow direct creation */ }
    }
    public class IntParamElement
    {
        internal IntParamElement() { /* disallow direct creation */ }
    }
    public class DoubleParamElement
    {
        internal DoubleParamElement() { /* disallow direct creation */ }
    }
    public class LocalElement
    {
        internal LocalElement() { /* disallow direct creation */ }
    }

    public static readonly ElementKind.RegularElement Regular = new RegularElement();
    public static readonly ElementKind.IntParamElement IntParam = new IntParamElement();
    public static readonly ElementKind.DoubleParamElement DoubleParam = new DoubleParamElement();
    public static readonly ElementKind.LocalElement Local = new LocalElement();
}

public class DataElement
{
    private string FName;
    public string Name { get { return FName; } }

    private bool FPersistent;
    public bool Persistent { get { return FPersistent; } }

    protected DataElement(string name)
    {
        FName = name;
        // ... other initialization ...
    }

    public DataElement(ElementKind.RegularElement kind, string name)
        : this(name)
    {
        FPersistent = true;
    }

    public DataElement(ElementKind.IntParamElement kind, string name, int defaultInt)
        : this(name)
    {
        FPersistent = true;
        // ... use defaultInt ...
    }

    public DataElement(ElementKind.DoubleParamElement kind, string name, double defaultDouble)
        : this(name)
    {
        FPersistent = true;
        // ... use defaultDouble ...
    }

    public DataElement(ElementKind.LocalElement kind, string name)
        : this(name)
    {
        FPersistent = false;

        // ... other code for "local" elements ...
    }
}

public class Program
{
    public void Run()
    {
        DataElement data = new DataElement(ElementKind.Regular, "Element");
        DataElement parI = new DataElement(ElementKind.IntParam, "IntElement", 22);
        DataElement parD = new DataElement(ElementKind.DoubleParam, "DblElement", 3.14);
        DataElement locl = new DataElement(ElementKind.Local, "LocalElement");
    }
}

一切都很好地编译和工作。那我这里有什么问题?.NET框架设计指南,以及名为Microsoft FxCop的工具。在通过这个工具运行最后一个代码之后,我遇到了多个中断问题(见下文)。
问题是:如何设计我的类以符合.NET设计指南和最佳实践?
中断-确定性90%-嵌套类型不应可见-ElementKind+RegularElement
中断-确定性90%-嵌套类型不应可见-ElementKind+IntParameter
中断-确定性90%-嵌套类型不应可见-ElementKind+DoubleParameter
中断-确定性90%-嵌套类型不应可见-ElementKind+LocalElement
断开-确定性90%-静态持有者类型不应具有构造函数-ElementKind
中断-确定性75%-标识符不应包含类型名-dataelement..ctor(elementkind+intparametelement,system.string,system.int32)
中断-确定性75%-标识符不应包含类型名-dataelement..ctor(elementkind+doubleparametelement,system.string,system.double)
不中断-确定性25%-不要声明只读可变引用类型-elementkind.正则
不中断-确定性25%-不要声明只读可变引用类型-ElementKind。intparam
非中断-确定性25%-不要声明只读可变引用类型-elementKind。doubleparam
不中断-确定性25%-不要声明只读可变引用类型-elementkind.local

最佳答案

首先,我将用class替换嵌套的“elementkind”enum

public enum ElementKind
{
    RegularElement,
    IntParamElement,
    DoubleParamElement,
    LocalElement
}

此外,我认为您的delphi代码不需要映射到构造函数。您最好使用静态factory methods返回aDataElement。例如:
public static DataElement Create(string name)
{
    return new DataElement(ElementKind.Regular, name);
}

public static DataElement CreateParam(string name, int defaultInt);
{
    return new DataElement(ElementKind.IntParam, name);
    // ... use defaultInt ...
}

// similar to above
public static DataElement CreateParam(string name, double defaultDouble);
public static DataElement CreateLocal(string name);

因为您使用工厂函数来创建dataelement对象,所以应该将构造函数设为私有。
然后,您将更新run()函数以使用以下内容:
public void Run()
{
    DataElement data = DataElement.Create("Element");
    DataElement parI = DataElement.CreateParam("IntElement", 22);
    DataElement parD = DataElement.CreateParam("DblElement", 3.14);
    DataElement locl = DataElement.CreateLocal("LocalElement");
}

更新:我包含了对Run()函数的建议更改,并更正了基本的Create()工厂方法(我相信它应该返回“regular”DataElement)。

08-28 15:57