向下转换 C# .NET
Downcasting C# .NET
这是我的例子:
public class Person
{
public string Name { get; set; }
}
public class Client : Person
{
public string LastName { get; set; }
}
public class Test
{
Person p = new Person();
Client c = (Client)p; //throws exception
}
既然Client继承自Person,为什么我做不到呢?如果我可以,但这是错误的方法,我该怎么做?
OBS:我知道上面的例子可以做到:
Person p = new Client();
Client c = (Client)p;
A Person
不是 Client
因此您希望编译器如何转换它?试试这个,你会得到一个 null
分配:
Client c = p as Client;
换句话说:编译器错误消失了,但 c 将永远是 null
。
这会引发异常,因为 p
不是客户端。 p
已创建为 person
。您可以创建一个 client
对象并将其转换为它的基类 person
,但不是这样。
实际上,稍微绕一下,您就可以进行这样的转换,但是,它需要一个额外的父 class 用于其他两个 class,以及一个隐式运算符来将 Client 转换为一个人(虽然这可能不是你最初想要的)
class Program
{
public abstract class BasePerson
{
public string FirstName { get; set; }
}
public class Person : BasePerson
{
}
public class Client : BasePerson
{
public string LastName { get; set; }
public static implicit operator Client(Person p)
{
if (p == null)
{
return null;
}
return new Client { FirstName = p.FirstName };
}
}
static void Main(string[] args)
{
Person p = new Person { FirstName = "Test" };
Client c = (Client)p;
Console.WriteLine(c.FirstName);
Console.ReadLine();
}
}
这将编译并向客户提供 FirstName,并可能提供姓氏,但是,正如我所说,这可能不是您想要的,只是让您的代码编译的可能性,并且 运行 变化最小...
更新
正如评论中所讨论的,如果我需要实现这样的转换,我更愿意通过
创建辅助方法
public class Client : Person
{
public static Client GetClientFromPerson(Person p)
{
if (p == null)
{
return null;
}
return new Client { FirstName = p.FirstName };
}
}
这将导致:
Client c = Client.GetClientFromPerson(p);
添加第二个构造函数
public class Client : Person
{
public string LastName { get; set; }
public Client()
{
}
public Client(Person p) : this()
{
FirstName = p.FirstName;
}
}
这将导致:
Client c = new Client(p);
这将使其他人审查代码变得容易得多,也可能在将来进行维护,并且不需要您更改您现在拥有的继承
子代可以继承其父代的所有属性class,但父代只能继承公共属性。这并不意味着您可以将父对象直接分配给它的子对象。
您可以使用 as 和 is 运算符来完成。
通过使用 as 运算符,如果变量不为空,则 class 可转换为其他 class
Person p = new Person();
var conversionResultFromPersonToClient = p as Client;
if(conversionResultFromPersonToClient != null)
//it means you can cast from person to client
第二种方法是使用 is 运算符
Person p = new Person();
Client c = new Client();
if(p is Client)
//Then you can cast person to client
c = (Client)p;
这是我的例子:
public class Person
{
public string Name { get; set; }
}
public class Client : Person
{
public string LastName { get; set; }
}
public class Test
{
Person p = new Person();
Client c = (Client)p; //throws exception
}
既然Client继承自Person,为什么我做不到呢?如果我可以,但这是错误的方法,我该怎么做?
OBS:我知道上面的例子可以做到:
Person p = new Client();
Client c = (Client)p;
A Person
不是 Client
因此您希望编译器如何转换它?试试这个,你会得到一个 null
分配:
Client c = p as Client;
换句话说:编译器错误消失了,但 c 将永远是 null
。
这会引发异常,因为 p
不是客户端。 p
已创建为 person
。您可以创建一个 client
对象并将其转换为它的基类 person
,但不是这样。
实际上,稍微绕一下,您就可以进行这样的转换,但是,它需要一个额外的父 class 用于其他两个 class,以及一个隐式运算符来将 Client 转换为一个人(虽然这可能不是你最初想要的)
class Program
{
public abstract class BasePerson
{
public string FirstName { get; set; }
}
public class Person : BasePerson
{
}
public class Client : BasePerson
{
public string LastName { get; set; }
public static implicit operator Client(Person p)
{
if (p == null)
{
return null;
}
return new Client { FirstName = p.FirstName };
}
}
static void Main(string[] args)
{
Person p = new Person { FirstName = "Test" };
Client c = (Client)p;
Console.WriteLine(c.FirstName);
Console.ReadLine();
}
}
这将编译并向客户提供 FirstName,并可能提供姓氏,但是,正如我所说,这可能不是您想要的,只是让您的代码编译的可能性,并且 运行 变化最小...
更新
正如评论中所讨论的,如果我需要实现这样的转换,我更愿意通过
创建辅助方法
public class Client : Person { public static Client GetClientFromPerson(Person p) { if (p == null) { return null; } return new Client { FirstName = p.FirstName }; } }
这将导致:
Client c = Client.GetClientFromPerson(p);
添加第二个构造函数
public class Client : Person { public string LastName { get; set; } public Client() { } public Client(Person p) : this() { FirstName = p.FirstName; } }
这将导致:
Client c = new Client(p);
这将使其他人审查代码变得容易得多,也可能在将来进行维护,并且不需要您更改您现在拥有的继承
子代可以继承其父代的所有属性class,但父代只能继承公共属性。这并不意味着您可以将父对象直接分配给它的子对象。
您可以使用 as 和 is 运算符来完成。
通过使用 as 运算符,如果变量不为空,则 class 可转换为其他 class
Person p = new Person();
var conversionResultFromPersonToClient = p as Client;
if(conversionResultFromPersonToClient != null)
//it means you can cast from person to client
第二种方法是使用 is 运算符
Person p = new Person();
Client c = new Client();
if(p is Client)
//Then you can cast person to client
c = (Client)p;