我最近开始在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#中实现我想要做的事情?
基本上将值传递给主对象的构造函数,主对象在自己的主体中指出要传递给基类的值。
答案 0 :(得分:6)
您可以在构造函数中调用静态方法。虽然非常不标准。
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;
}
}
答案 1 :(得分:4)
其他答案未能理解的是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);
}
}
}
关键是可以想象员工在没有数据库的情况下使用,例如在单元测试中。
答案 2 :(得分:3)
您可以重构共享功能:
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);
}
}
请注意,我将参数名称的大小更改为更标准的低驼峰大小写。
不要这样做。类不应该依赖外部数据源来创建自己的实例。创建一个单独的类(存储库,工厂,等等),从数据库中提取数据并填充空白对象的属性。我以前做的是将Id(我的db表中的主键)传递给对象构造函数,然后从构造函数中的db中获取数据。
将数据库逻辑放在类的构造函数中会阻止独立于数据源的测试。
答案 3 :(得分:1)
如何使用静态方法实例化您的类?
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);
答案 4 :(得分:0)
某些语言允许您从派生构造函数中显式调用基础构造函数。
C#不是这样的语言。
在这种情况下,由于EmployeeId与UserId不同并且在派生类构造函数中计算,因此您必须从Employee构造函数设置它,而不是将其作为参数传递给基类构造函数。
UserId的基类中的后备存储需要设置为protected,或者您需要提供受保护的属性或方法来设置它。
答案 5 :(得分:0)
您不想做的事情(并且可能不应该 - 感谢,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);
}
}