Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#派生类和基构造函数参数逻辑_C#_Oop_Inheritance - Fatal编程技术网

C#派生类和基构造函数参数逻辑

C#派生类和基构造函数参数逻辑,c#,oop,inheritance,C#,Oop,Inheritance,我有一个基本类: public class Base { public Base(X x ,Y y){ this.x = x; this.y = y; } public X x{get;} public Y y{get;} } 还有一个嘲笑者: public class Derive : Base { public Derive(Z z, Q q) :Base (? ?) { } private

我有一个基本类:

public class Base
{
    public Base(X x ,Y y){
        this.x = x;
        this.y = y;
    }

    public X x{get;}
    public Y y{get;}
}
还有一个嘲笑者:

public class Derive : Base
{
    public Derive(Z z, Q q) :Base (? ?)
    {
    }

    private void ConstructXY(Z z, Q q)
    {
        //Advanced logic for creating an X and a Y
        if(q.something == 5){
            this.x = new X(28); 
        }
        else{
            this.x = new X(25);
        }

        if(this.x.something == 25 && q == 9){
            this.y = new Y(1);
        }
        else{
            this.y = new Y(5)
        }
    }
}

现在,如果没有“高级”逻辑,我无法正确地调用基本构造函数。我曾经能够从派生.ctor()调用ConstructXY(),并从那里设置x和y,这不再有效,因为我删除了x和y设置器。我的现实生活场景包含了更多的逻辑,因此我不愿意制造三元混乱。

为什么不将基类设置器声明为私有:

public class Base
{
    public Base(X x ,Y y){
        this.x = x;
        this.y = y;
    }

    public X x{get; private set;}
    public Y y{get; private set;}
}

这样,您仍然可以在构造函数中设置它们,并且它们不可以在外部设置?

为什么不将基类设置器声明为私有的:

public class Base
{
    public Base(X x ,Y y){
        this.x = x;
        this.y = y;
    }

    public X x{get; private set;}
    public Y y{get; private set;}
}

这样,您仍然可以在构造函数中设置它们,并且它们在外部不可设置?

我不太喜欢这种方式,如果可能的话会避免这种方式,但是您可以在调用
base
时使用三元语句:

public Derive(Z z, Q q)
    : base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))

我真的不喜欢这样做,如果可能的话,我会避免这样做,但是您可以在对
base
的调用中使用三元语句:

public Derive(Z z, Q q)
    : base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))
如果“高级”逻辑适合于静态方法,则可以调用它

下面是一种使用C#7中提供的元组的方法:

如果“高级”逻辑适合于静态方法,则可以调用它

下面是一种使用C#7中提供的元组的方法:


如果无法更改基类中
X
Y
的访问修饰符,以便子类可以访问这些修饰符,则必须遵循约定,将构造函数保留为可以设置这些成员的唯一可能位置

添加更多逻辑以计算这些值的唯一方法是使用静态方法,例如:

public class Derive : Base
{
    public Derive(Z z, Q q)
        : base(ConstructX(q), ConstructY(q, z))
    { }

    private static X ConstructX(Q q)
    {
        if (q.something == 5)
            return new X(28);
        else
            return new X(25);
    }

    private static Y ConstructY(Q q, Z z)
    {
        if (z.something == 25 && q.something == 9)
            return new Y(1);
        else
            return new Y(5);
    }
}
由于这些是单独的方法调用,您无法“同时”计算这两个值,因此您无法使
Y
的结果取决于
X
的结果,而不重新基于
Z
Q
进行计算

解决此问题的另一种方法是完全删除
derivate
上的公共构造函数,并提供一个静态工厂方法:

public class Derive : Base
{
    private Derive(X x, Y y)
        : base(x, y)
    { }

    public static Derive Create(Z z, Q q)
    {
        // here you can use your original logic to calculate X and Y
        X x = …
        Y y = …

        return new Derive(x, y);
    }
}
根据这些计算的复杂性,这可能是更好的解决方案。如果您确实需要原始的
Z
Q
值,只需扩展私有构造函数即可获取这些值并存储它们:

private Derive(Z z, Q q, X x, Y y)
    : base(x, y)
{
    this.Z = z;
    this.Q = q;
}

如果无法更改基类中
X
Y
的访问修饰符,以便子类可以访问这些修饰符,则必须遵循约定,将构造函数保留为可以设置这些成员的唯一可能位置

添加更多逻辑以计算这些值的唯一方法是使用静态方法,例如:

public class Derive : Base
{
    public Derive(Z z, Q q)
        : base(ConstructX(q), ConstructY(q, z))
    { }

    private static X ConstructX(Q q)
    {
        if (q.something == 5)
            return new X(28);
        else
            return new X(25);
    }

    private static Y ConstructY(Q q, Z z)
    {
        if (z.something == 25 && q.something == 9)
            return new Y(1);
        else
            return new Y(5);
    }
}
由于这些是单独的方法调用,您无法“同时”计算这两个值,因此您无法使
Y
的结果取决于
X
的结果,而不重新基于
Z
Q
进行计算

解决此问题的另一种方法是完全删除
derivate
上的公共构造函数,并提供一个静态工厂方法:

public class Derive : Base
{
    private Derive(X x, Y y)
        : base(x, y)
    { }

    public static Derive Create(Z z, Q q)
    {
        // here you can use your original logic to calculate X and Y
        X x = …
        Y y = …

        return new Derive(x, y);
    }
}
根据这些计算的复杂性,这可能是更好的解决方案。如果您确实需要原始的
Z
Q
值,只需扩展私有构造函数即可获取这些值并存储它们:

private Derive(Z z, Q q, X x, Y y)
    : base(x, y)
{
    this.Z = z;
    this.Q = q;
}

使用静态方法进行转换。像这样

public class Derive : Base
{
    public Derive(Z z, Q q) :base (ConvertToX(z, q), ConvertToY(z, q))
    {
    }

    private static X ConvertToX(Z z, Q q) {
        if(q.something == 5){
            return new X(28); 
        }
        return new X(25);
    }

    private static Y ConvertToY(Z z, Q q) {
        // TODO
    }
}

使用静态方法进行转换。像这样

public class Derive : Base
{
    public Derive(Z z, Q q) :base (ConvertToX(z, q), ConvertToY(z, q))
    {
    }

    private static X ConvertToX(Z z, Q q) {
        if(q.something == 5){
            return new X(28); 
        }
        return new X(25);
    }

    private static Y ConvertToY(Z z, Q q) {
        // TODO
    }
}

该构造函数应该读取
公共派生(zz,qq):Base(?)
,还是
公共派生(zz,qq):Base(?)
?C的哪个版本?我想知道是否可以用C#7中的元组做一些聪明的事情。@TimothyGroote它应该是based是构造函数应该读
公共派生(Z Z,Q Q Q):Base(?)
,还是
公共派生(Z Z,Q Q):Base(?)
?什么版本的C#?我想知道是否可以用C#7中的元组做一些聪明的事情。@TimothyGroote它应该是base
public X{get;}
在构造过程中才可以设置。这只是一个小小的简写。
public X{get;}
仅在构建期间可设置。这只是一个小小的简化。请注意,这需要更改基类以接受
X
Y
作为单个参数。可能无法更改基类。如果您只想在派生类中访问新构造函数,则可以将其设置为受保护的。在C#7之前,您可能也可以做类似的事情,只需传入一个
元组
,注意,这需要更改基类,将
X
Y
作为单个参数。可能无法更改基类。如果您只想在派生类中访问新构造函数,则可以将其设置为受保护的。你也可以在C#7之前做类似的事情,只需传入一个
元组
OP,问题中提到他们“不愿意制造三元混乱”——不过,你可以简单地将逻辑移到静态方法,以避免其他答案中所示的“混乱”。@poke我在阅读时不知何故忽略了这一点,然而,这是一个可行的选择,因为其他答案涵盖了将其移到静态方法,所以我不会编辑我的答案并保持原样。是的,没关系:)OP在问题中提到他们“不愿意制造三元混乱”——不过,您可以简单地将逻辑移到静态方法,以避免其他答案中显示的这种“混乱”。@poke我在阅读时不知何故忽略了这一点,但是,这是一个可行的选择,因为其他答案涵盖了将其移到静态方法,所以我不会编辑我的答案并保持原样。是的,这很好:)