从普通 interface/abstract class 向下转换失败
Downcasting failing from common interface/abstract class
我有两个 classes - Expert 和 Farmer,它们都有一些共同的特征,因此实现了一个抽象的 class User。用户实现接口 IUser。在我的应用程序中,最初已填写公共字段,但随后用户指示它们是否为 Expert/Farmer。
此时,我想将我当前的对象转换为 Expert 或 Farmer 以填充各自独特的字段。我当前的方法是声明 IUser user = new Farmer();
,然后尝试在适当的时间适当地转换:Farmer farmer = user as Farmer
或 Expert expert = user as Expert
。然而,转换为 Expert 总是失败,尽管它们都实现相同的接口和抽象 class。
- 为什么这个转换失败了?
- 使用继承巧妙地解决这个问题的正确方法是什么?显然,可以创建
User
抽象 class 中定义的函数 createUser()
或 createFarmer()
或者只是实例化 User
和 Farmer
并填充初始值两者中的字段,在拆分时采用任何需要的实例,但这些都不是特别优雅。
专家定义:
public partial class Expert : User
{
public override Guid Id { get; set; }
[StringLength(200)]
public override string Name { get; set; }
[Key]
[StringLength(10)]
public override string phone { get; set; }
[StringLength(50)]
public override string state { get; set; }
[StringLength(50)]
public override string district { get; set; }
[StringLength(6)]
public override string PIN { get; set; }
public override double geolat { get; set; }
public override double geolong { get; set; }
public override int v { get; set; }
public override int h { get; set; }
public override string AzureImageURL { get; set; }
//IParty properties
public override string ServiceUrl { get; set; }
public override string ChannelId { get; set; }
public override string PartyChannelAccountId { get; set; }
public override string PartyChannelAccountName { get; set; }
public override string BotChannelAccountId { get; set; }
public override string BotChannelAccountName { get; set; }
public override string ConversationAccountId { get; set; }
public override string ConversationAccountName { get; set; }
//Expert specific properties
public double price { get; set; }
public int totalRating { get; set; }
public int numberOfRating { get; set; }
public string description { get; set; }
public string languages { get; set; }
double _sortIndex = double.Nan
}
农民的定义:
public partial class Farmer : User, IVisualizable
{
//User override fields
[Key]
public override Guid Id { get; set; }
[StringLength(200)]
public override string Name { get; set; }
[StringLength(10)]
public override string phone { get; set; }
[StringLength(50)]
public override string state { get; set; }
[StringLength(50)]
public override string district { get; set; }
[StringLength(6)]
public override string PIN { get; set; }
public override double geolat { get; set; }
public override double geolong { get; set; }
public override int v { get; set; }
public override int h { get; set; }
public override string AzureImageURL { get; set; }
//IParty properties
public override string ServiceUrl { get; set; }
public override string ChannelId { get; set; }
public override string PartyChannelAccountId { get; set; }
public override string PartyChannelAccountName { get; set; }
public override string BotChannelAccountId { get; set; }
public override string BotChannelAccountName { get; set; }
public override string ConversationAccountId { get; set; }
public override string ConversationAccountName { get; set; }
//Farmer specific properties
[StringLength(12)]
public string AadhaarNum { get; set; }
public int cropId { get; set; }
[StringLength(1)]
public string acreage { get; set; }
/// <summary>
/// Constructor calling base - sets Guid of farmer
/// </summary>
public Farmer() : base()
{
}
}
用户定义:
public abstract class User : IUser
{
public abstract Guid Id { get; set; }
public abstract string Name { get; set; }
public abstract string phone { get; set; }
public abstract string state { get; set; }
public abstract string district { get; set; }
public abstract string PIN { get; set; }
public abstract double geolat { get; set; }
public abstract double geolong { get; set; }
public abstract int v { get; set; }
public abstract int h { get; set; }
public abstract string AzureImageURL { get; set; }
public abstract string ServiceUrl { get; set; }
public abstract string ChannelId { get; set; }
public abstract string PartyChannelAccountId { get; set; }
public abstract string PartyChannelAccountName { get; set; }
public abstract string BotChannelAccountId { get; set; }
public abstract string BotChannelAccountName { get; set; }
public abstract string ConversationAccountId { get; set; }
public abstract string ConversationAccountName { get; set; }
/// <summary>
/// Creates a new User with a new Guid already set.
/// </summary>
public User()
{
Id = Guid.NewGuid();
}
}
IUser 的定义:
public interface IUser : IParty
{
Guid Id { get; set; }
string Name { get; set; }
string state { get; set; }
string district { get; set; }
string PIN { get; set; }
double geolat { get; set; }
double geolong { get; set; }
int v { get; set; }
int h { get; set; }
string AzureImageURL { get; set; }
}
谢谢!
您希望农民如何成为专家?即使if它们实现了相同的公共接口,它们也是完全不同的。特别是您的 classes 有一些不常见的成员:
class Expert
{
public string languages { get; set; }
}
class Farmer
{
public string AadhaarNum { get; set; }
}
languages
应该如何转化为AadhaarNum
?那是不可能的,因此没有自动投射。您必须创建一些自己的转换或转换,例如
var farmer = new Farmer(expert);
这假设您在两个 classes 中都有一个复制构造函数:
class Farmer
{
public Farmer(IUser user)
{
this.Name = user.Name;
...
// also set the members that exist only on farmer
}
}
相应地 Expert
-class。
或者,您可以在抽象基础中引入一些工厂方法-class。然而,这有一个缺点,即您的 base-class 需要知道所有可能的子类型。因此引入新的 sub-classes 会导致改变 base-class.
我有两个 classes - Expert 和 Farmer,它们都有一些共同的特征,因此实现了一个抽象的 class User。用户实现接口 IUser。在我的应用程序中,最初已填写公共字段,但随后用户指示它们是否为 Expert/Farmer。
此时,我想将我当前的对象转换为 Expert 或 Farmer 以填充各自独特的字段。我当前的方法是声明 IUser user = new Farmer();
,然后尝试在适当的时间适当地转换:Farmer farmer = user as Farmer
或 Expert expert = user as Expert
。然而,转换为 Expert 总是失败,尽管它们都实现相同的接口和抽象 class。
- 为什么这个转换失败了?
- 使用继承巧妙地解决这个问题的正确方法是什么?显然,可以创建
User
抽象 class 中定义的函数createUser()
或createFarmer()
或者只是实例化User
和Farmer
并填充初始值两者中的字段,在拆分时采用任何需要的实例,但这些都不是特别优雅。
专家定义:
public partial class Expert : User
{
public override Guid Id { get; set; }
[StringLength(200)]
public override string Name { get; set; }
[Key]
[StringLength(10)]
public override string phone { get; set; }
[StringLength(50)]
public override string state { get; set; }
[StringLength(50)]
public override string district { get; set; }
[StringLength(6)]
public override string PIN { get; set; }
public override double geolat { get; set; }
public override double geolong { get; set; }
public override int v { get; set; }
public override int h { get; set; }
public override string AzureImageURL { get; set; }
//IParty properties
public override string ServiceUrl { get; set; }
public override string ChannelId { get; set; }
public override string PartyChannelAccountId { get; set; }
public override string PartyChannelAccountName { get; set; }
public override string BotChannelAccountId { get; set; }
public override string BotChannelAccountName { get; set; }
public override string ConversationAccountId { get; set; }
public override string ConversationAccountName { get; set; }
//Expert specific properties
public double price { get; set; }
public int totalRating { get; set; }
public int numberOfRating { get; set; }
public string description { get; set; }
public string languages { get; set; }
double _sortIndex = double.Nan
}
农民的定义:
public partial class Farmer : User, IVisualizable
{
//User override fields
[Key]
public override Guid Id { get; set; }
[StringLength(200)]
public override string Name { get; set; }
[StringLength(10)]
public override string phone { get; set; }
[StringLength(50)]
public override string state { get; set; }
[StringLength(50)]
public override string district { get; set; }
[StringLength(6)]
public override string PIN { get; set; }
public override double geolat { get; set; }
public override double geolong { get; set; }
public override int v { get; set; }
public override int h { get; set; }
public override string AzureImageURL { get; set; }
//IParty properties
public override string ServiceUrl { get; set; }
public override string ChannelId { get; set; }
public override string PartyChannelAccountId { get; set; }
public override string PartyChannelAccountName { get; set; }
public override string BotChannelAccountId { get; set; }
public override string BotChannelAccountName { get; set; }
public override string ConversationAccountId { get; set; }
public override string ConversationAccountName { get; set; }
//Farmer specific properties
[StringLength(12)]
public string AadhaarNum { get; set; }
public int cropId { get; set; }
[StringLength(1)]
public string acreage { get; set; }
/// <summary>
/// Constructor calling base - sets Guid of farmer
/// </summary>
public Farmer() : base()
{
}
}
用户定义:
public abstract class User : IUser
{
public abstract Guid Id { get; set; }
public abstract string Name { get; set; }
public abstract string phone { get; set; }
public abstract string state { get; set; }
public abstract string district { get; set; }
public abstract string PIN { get; set; }
public abstract double geolat { get; set; }
public abstract double geolong { get; set; }
public abstract int v { get; set; }
public abstract int h { get; set; }
public abstract string AzureImageURL { get; set; }
public abstract string ServiceUrl { get; set; }
public abstract string ChannelId { get; set; }
public abstract string PartyChannelAccountId { get; set; }
public abstract string PartyChannelAccountName { get; set; }
public abstract string BotChannelAccountId { get; set; }
public abstract string BotChannelAccountName { get; set; }
public abstract string ConversationAccountId { get; set; }
public abstract string ConversationAccountName { get; set; }
/// <summary>
/// Creates a new User with a new Guid already set.
/// </summary>
public User()
{
Id = Guid.NewGuid();
}
}
IUser 的定义:
public interface IUser : IParty
{
Guid Id { get; set; }
string Name { get; set; }
string state { get; set; }
string district { get; set; }
string PIN { get; set; }
double geolat { get; set; }
double geolong { get; set; }
int v { get; set; }
int h { get; set; }
string AzureImageURL { get; set; }
}
谢谢!
您希望农民如何成为专家?即使if它们实现了相同的公共接口,它们也是完全不同的。特别是您的 classes 有一些不常见的成员:
class Expert
{
public string languages { get; set; }
}
class Farmer
{
public string AadhaarNum { get; set; }
}
languages
应该如何转化为AadhaarNum
?那是不可能的,因此没有自动投射。您必须创建一些自己的转换或转换,例如
var farmer = new Farmer(expert);
这假设您在两个 classes 中都有一个复制构造函数:
class Farmer
{
public Farmer(IUser user)
{
this.Name = user.Name;
...
// also set the members that exist only on farmer
}
}
相应地 Expert
-class。
或者,您可以在抽象基础中引入一些工厂方法-class。然而,这有一个缺点,即您的 base-class 需要知道所有可能的子类型。因此引入新的 sub-classes 会导致改变 base-class.