C# 具有未知参数的构造函数

C# 具有未知参数的构造函数,c#,class,oop,inheritance,constructor,C#,Class,Oop,Inheritance,Constructor,我最近开始用C语言编程,在PHP上度过了我的大部分时间 在PHP中,我可以这样做: class User { public __construct($UserId) { // Do stuff } } class Employee extends User { public __construct($EmployeeId) { // Look up the UserId connected to $EmployeeId

我最近开始用C语言编程,在PHP上度过了我的大部分时间

在PHP中,我可以这样做:

class User
{
    public __construct($UserId)
    {
        // Do stuff
    }
}

class Employee extends User
{
    public __construct($EmployeeId)
    {
        // Look up the UserId connected to $EmployeeId
        $UserId = hypothetical_get_user_id_func($EmployeeId);
        parent::__construct($UserId);
    }
}
但是,在C中,我似乎没有这种可能性,因为在$UserId进入第一个构造函数之前,我似乎必须知道它

public class User
{
    public User(int UserId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int EmployeeId) : base(***) // I don't know this value yet?
    {
        // This is where I would find the User Id, and would like to pass
        // it to the User class constructor.
    }
}
有什么方法可以实现我在C语言中的目标吗


基本上,将值传递给主对象的构造函数,主对象在其自身的主体中确定要传递给基类的值。

某些语言允许您从派生构造函数中显式调用基类构造函数

public class User
{
    public User(int UserId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int EmployeeId) : base(***) // I don't know this value yet?
    {
        // This is where I would find the User Id, and would like to pass
        // it to the User class constructor.
    }
}
C不是这样一种语言

在这种情况下,由于EmployeeId与UserId不同,并且是在派生类构造函数中计算的,因此必须从Employee构造函数中设置它,而不是将其作为参数传递给基类构造函数

public class User
{
    public User(int UserId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int EmployeeId) : base(***) // I don't know this value yet?
    {
        // This is where I would find the User Id, and would like to pass
        // it to the User class constructor.
    }
}

UserId基类中的备份存储需要设置为受保护,或者您需要提供受保护的属性或方法来设置它。

您可以在构造函数中调用静态方法。但是非常不标准

public class User
{
    public User(int userId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int employeeId) : base(GetUserId(employeeId))
    {

    }

    public static int GetUserId(int employeeId)
    {           
        return employeeId - 5;
    }
}

您可以重构为共享函数:

public class User
{

    protected User() {}

    public User(int userId)
    {
        Init(userId);
    }

    protected void Init(int userId)
    {
        // Do stuff
    }

}

public class Employee : User
{
    public Employee(int employeeId)  
    {
        // find user Id here

        Init(userId);
    }
}
注意,我将参数名称的大小写改为更标准的小写


我习惯于将db表中的Id主键传递给对象构造函数,然后从构造函数中的db获取数据

public class User
{
    public User(int UserId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int EmployeeId) : base(***) // I don't know this value yet?
    {
        // This is where I would find the User Id, and would like to pass
        // it to the User class constructor.
    }
}
不要那样做。类不应该依赖外部数据源来创建自身的实例。创建一个单独的类存储库,工厂,无论从数据库中提取数据,并填充空白对象的属性。
将数据库逻辑放在类的构造函数中可以防止独立于数据源进行测试

您想做的事情不是,也可能不应该是-谢谢,PHP是可能的,但是像这样的事情就足够了:

public class User
{
    protected User() {
        // Do things here
    }

    public User(int UserId)
    {
        Init(UserId);
    }

    protected void Init(int UserId) {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int EmployeeId) : base()
    {
        int UserId;
        // Find UserId

        Init(UserId);
    }
}
关注点分离 其他答案没有理解的是PHP和C有非常不同的编码标准

PHP中的一个常见模式是

class User
{
    public __construct($UserId)
    {
        // Do stuff
    }
}

class Employee extends User
{
    public __construct($EmployeeId)
    {
        // Look up the UserId connected to $EmployeeId
        $UserId = get_userid_from_database($EmployeeId);
        parent::__construct($UserId);
    }
}
但在C语言中,这绝对不会被认为是一个好的设计

在.net中实现此功能的典型方法将更接近

public class User
{
    public User(int userId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    public Employee(int employeeId, int userId) : base(userId) // I don't know this value yet?
    {
        // This is where I would find the User Id, and would like to pass
        // it to the User class constructor.
    }
}

public class EmployeeRepository
{
    public Employee GetEmployee(int employeeId)
    {
        using(var connection = new SqlConnection(..)
        {
            //blah blah blah
            return new Employee(employeeId, userId);
        }
    }
}

要点是Employee可能在没有数据库的情况下使用,例如在单元测试中。

使用静态方法实例化类怎么样

public class User
{
    public User(int UserId)
    {
        // Do stuff
    }
}

public class Employee : User
{
    private Employee(int userID) : base(userID) { }

    public static Employee GetEmployee(int employeeID)
    {
        var userID = GetUserIDFromEmployeeID(employeeID);

        return new Employee(userID);
    }
}
然后在您的呼叫代码中,您将:

var employee = Employee.GetEmployee(someValue);

您必须将userId作为另一个参数。这是不可能的。但您可以调用静态方法并传递其结果。正如SLaks所说,这是不可能的。但是有很好的理由。构造函数中不应包含业务逻辑。你所说的听起来更像是一个DAL/工厂。在C语言中,我们鼓励坚实的设计原则,而您正在尝试的是打破坚实的关注点部分的分离。很遗憾,我会…>\u