Sco*_*ker 23 c# casting membershipuser
我有一个继承自MembershipUser的自定义CustomMembershipUser.
public class ConfigMembershipUser : MembershipUser
{
// custom stuff
}
Run Code Online (Sandbox Code Playgroud)
我使用Linq-to-SQL从数据库读取并获取User实体; 要使此功能成为MembershipUser,我已定义了一个显式转换:
public static explicit operator MembershipUser(User user)
{
DateTime now = DateTime.Now;
if (user == null) return null;
return new MembershipUser("MagicMembershipProvider",
user.DisplayName, user.Id,
user.Email, "", "", true, false,
now, now, now, now, now);
}
Run Code Online (Sandbox Code Playgroud)
这个演员工作正常:
MembershipUser memUser = (MembershipUser) entityUser;
Run Code Online (Sandbox Code Playgroud)
但是,对CustomMembershipUser的第二次强制转换失败:
MembershipUser memUser = (MembershipUser) entityUser;
CustomMembershipUser custUser = (CustomMembershipUser) memUser;
Run Code Online (Sandbox Code Playgroud)
如果我将演员阵容改为
CustomMembershipUser custUser = memUser;
Run Code Online (Sandbox Code Playgroud)
我得到一个intellisense错误告诉我隐式强制转换不起作用,但存在显式强制转换.
...最重要的是,我无法明确定义从基类到子类的强制转换.我尝试过但失败了.我最不了解的是为什么从基类到子类的转换会失败?根据定义,子类具有基类的所有属性,因此问题是什么.
我试图定义从MembershipUser到CustomMembershipUser的显式转换(首先我为转换定义了一个私有构造函数):
private ConfigMembershipUser(MembershipUser user)
: base(user.ProviderName, user.UserName, user.ProviderUserKey, user.Email,
user.PasswordQuestion, user.Comment, user.IsApproved, user.IsLockedOut,
user.CreationDate, user.LastLoginDate, user.LastActivityDate,
user.LastPasswordChangedDate, user.LastLockoutDate)
{
// initialize extended CustomMembershipUser stuff here
}
Run Code Online (Sandbox Code Playgroud)
然后我定义了我的自定义模型:
public static explicit operator CustomMembershipUser(MembershipUser user)
{
return new CustomMembershipUser(user);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
'CustomMembershipUser.explicit operator CustomMembershipUser(System.Web.Security.MembershipUser)':不允许在基类之间进行用户定义的转换.
所以...我不能从基类转换为子类?
Cam*_*ron 32
你已经反过来了:从基类的对象到子类的转换总是会失败,因为基类只有基类的属性(而不是子类).
因为,正如你所说,子类具有基类的所有属性(它是"is-a"基类对象),然后从子类到基类的转换将始终成功,但从不反过来.
换句话说,你可以把所有的豹都想象成猫,但是你不能把它当作豹子来对待它(除非它已经是豹子了).
您需要返回一个CustomMembershipUser对象而不是一个MembershipUser对象,或者定义另一个显式的强制转换函数,它通过创建一个新CustomMembershipUser对象将MembershipUsers转换为CustomMembershipUsers .你不能无处获得CustomMembershipUser对象; 它首先被创建,直接或通过实例化CustomMembershipUser(不是基类)的子类.
编辑:
我错误地定义了对子类的显式强制转换.这是不可能的(因为您看到的错误表明).你现在似乎与这个问题的提问者情况完全相同.转换并不是真正的方法 - 要么创建CustomMembershipUser对象(可以直接用作MembershipUser对象),要么编写一个接受a MembershipUser并创建一个的转换方法CustomMembershipUser.
从基础对象转换为子类对象的唯一时间是它已经是子类对象(但是保存它的变量属于基类类型).
Jef*_*dge 11
MembershipUser类型的变量可以包含CustomMembershipUser类型的对象,因为子类型是超类型的实例.但反过来却不是这样.
CustomMembershipUser可能包含不在MembershipUser上的成员.因此,CustomMembershipUser类型的变量不能保存MembershipUser类型的对象.否则,代码可能会尝试访问其中不包含的成员之一.
这失败了:
CustomMembershipUser custUser = memUser;
Run Code Online (Sandbox Code Playgroud)
因为你可以用这个来跟进:
custUser.CustomStuff(); // Oops! Can't call CustomStuff() on a MembershipUser object!
Run Code Online (Sandbox Code Playgroud)
"Explicit Cast Exists"消息
您获得"显式转换存在"消息的原因不是因为您已经创建了从User到MembershipUser的转换.(此处不涉及用户类型.)这是因为从超类型到子类型的显式转换始终存在.这是语言设计的一部分.这是为了支持您知道对象属于子类型并且您想要使用匹配的变量的scenerio.但是如果您对不属于目标类型的对象使用该显式强制转换,则会出现运行时错误(正如您所经历的那样).
关于铸造失败原因的进一步解释
在C#中,每个对象都有一个类型.该类型永远不会在对象的生命周期中更改.一旦你创建了一个Employee(例如),它将永远是一个Employee永远,或者直到垃圾收集,amen.
public class Person
{
public string Name {get; private set;}
public Person(string name)
{ Name = name; }
}
public class Employee : Person
{
public DateTime HireDate {get; private set;}
public Employee(string name, DateTime hireDate)
: base (name)
{ HireDate = hireDate; }
}
Run Code Online (Sandbox Code Playgroud)
如果您有一个Person类型的变量,那么该变量可以包含Employee对象,因为Employee是Person.
Employee mike = new Employee("Michael", DateTime.Now);
Person myBestBud = mike;
Run Code Online (Sandbox Code Playgroud)
这是一个非常简单的演员,因为它总是有效的.Person变量始终可以包含Employee对象.这样做的原因是因为系统知道它试图使用的每个Person成员都会因为继承而可用.
Console.WriteLine("Dude's name: " + myBestBud.Name);
Run Code Online (Sandbox Code Playgroud)
现在,让我们以另一种方式尝试.
Person johnny = new Person("Johnny Johnson");
Employee newHire = johnny; // ERROR - Attempt to assign...etc. An explicit cast is available...
Run Code Online (Sandbox Code Playgroud)
这会导致错误.从Person到Employee没有隐式转换,因为编译器无法保证Person变量包含Employee对象.这会导致编译时错误.所以,让我们尝试显式演员.
Employee newHire = (Employee)johnny;
Run Code Online (Sandbox Code Playgroud)
这将编译得很好.这是编译器允许的,因为有时Person变量将保存Employee对象.但这会在运行时失败.这将失败的原因是因为变量johnny没有雇员,因此不能将其视为一个雇员.因此抛出了无效的强制转换异常.
如果它没有抛出无效的强制转换异常,那么我们可以尝试这样做:
Console.WriteLine("Hired on: " + newHire.HireDate);
Run Code Online (Sandbox Code Playgroud)
但该属性不存在,因为该对象实际上是一个Person,而不是Employee.
所以你可以看到从子类型到超类型存在一个隐含的转换,因为它总是成功并且不会导致任何问题.存在从超类型到子类型的显式转换,因为只有在对象的运行时类型与变量赋值兼容时才有效.程序员应该知道它何时起作用,什么时候不起作用,并且只有当它起作用时才进行演员表演.否则,运行时将检测无效的强制转换并抛出异常.
现在,用户有时可以创建一个自定义转换运算符,可用于从一种类型转换为另一种类型.当发生这种情况时,会创建一个目标类型的全新对象.但是,这不能在继承层次结构中上下执行,因为这些转换已经由C#编译器提供.为了执行自定义转换运算符,源类型或目标类型不能是其他类型的祖先或后代.
| 归档时间: |
|
| 查看次数: |
60303 次 |
| 最近记录: |