C# 如何对具有相同成员的不同类型参数使用相同的函数?
这里是示例代码,我定义了两个类。如何使用C# 如何对具有相同成员的不同类型参数使用相同的函数?,c#,C#,这里是示例代码,我定义了两个类。如何使用Output函数输出两个不同类中具有相同名称的成员 class A { public string Name { get; set; } public int Age { get; set; } public string Email { get; set; } public A(string name, int age, string email) { Name = name; A
Output
函数输出两个不同类中具有相同名称的成员
class A
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B
{
public string Name { get; set; }
public int Age { get; set; }
public string Location { get; set; }
public B(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
void Output(object obj)
{
// How can I convert the object 'obj' to class A or class B
// in order to output its 'Name' and 'Age'
Console.WriteLine((A)obj.Name); // If I pass a class B in pararmeter, output error.
}
您必须:
INamed
,它有一个字符串Name
属性,这两个类都实现了该属性dynamic
,并使用它访问Name
属性(但实际上这与#1相同,因为动态分派将仅使用反射来获取Name
属性)在你的例子中-B不是从A中产生的,所以你不能将B转换成A 将B更改为从A继承,如
class B : A
{
...
}
也考虑你在B类的方法中要完成什么。 并且-如果您继承了,则可能不需要两次声明相同的成员。
您可以利用它绕过编译器,它会在运行时检查类型,因此您不需要强制转换:void Output(dynamic obj)
{
Console.WriteLine(obj.Name);
}
你可以做:
if ( obj.GetType() == typeof( A ) )
{
Console.WriteLine(((A)obj).Name);
}
else if ( obj.GetType() == typeof( B ) )
{
Console.WriteLine(((B)obj).Name);
}
您应该声明一个接口,该接口将描述两个类的公共部分:
interface I
{
string Name { get; set; }
int Age { get; set; }
}
然后在A
和B
中实现它:
class A : I
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B : I
{
public string Name { get; set; }
public int Age { get; set; }
public string Location { get; set; }
public B(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
并更改方法以获取I
作为参数:
void Output(I obj)
{
Console.WriteLine(obj.Name);
}
您可以使用
动态
、反射或继承。或者您可以复制该方法并利用方法重载
void Output(A obj)
{
// in order to output its 'Name' and 'Age'
Console.WriteLine(obj.Age);
Console.WriteLine(obj.Name);
}
void Output(B obj)
{
// in order to output its 'Name' and 'Age'
Console.WriteLine(obj.Age);
Console.WriteLine(obj.Name);
}
您需要为这两个类创建一个公共接口,以便编译器知道这两个类都可以提供某些功能(在您的情况下是名称和年龄):
A
和B
除了有一些类似的成员外,是否有其他关系?也就是说,它们可以从共享父类型继承吗?@Oded-我认为这也是一种方式。在这里使用dynamic
从来都不是最佳实践。另一个选项是为A
和B
重载输出
,并且有一个私有函数,在从每个函数中提取数据后,重载可以使用它。@Oded-这很有趣,因为我只是在你发表评论之前写了这个作为答案。我喜欢你的风格:Name
property是私有的吗?那么它将如何工作(除了反射)?<代码> b <代码>的实例构造函数被称为<代码> A<代码>(非法)。这是最后考虑的方法。我从来没有这样建议过。如果(obj是一个)等等,为什么不?你会因为运行时类型检查而受到多少性能损失?@MarcinJuraszek:这只是一种方法,但不要过早优化。在大型应用程序中,动态性能的这一点是微不足道的,也可以使名称
等获取
-仅在接口I
内。在这种情况下,A
和B
允许设置集
terprivate
,这在某些情况下是可取的(例如,可以将类型设置为不可变)。@JeppeStigNielsen说得对!但我的回答更像是他能走的一条路,所以我将保持现状。这就是我要做的。使用dynamic
解决这个问题是错误的方法。我注意到,建议dynamic
的答案中没有一个提到,更不用说解决使用dynamic
时由于Name
丢失、类型错误或是方法而不是属性等原因引发异常时该怎么办了。用编译时正确性来换取潜在的运行时错误是很糟糕的。谢谢。#3?@Eddie使用反射的任何效率问题通常都比直接属性调用慢,但它肯定会起作用。最后,您必须实际测量应用程序的性能,看看这是否是热点。很有可能,数据库访问和网络调用之类的事情会大大超过一点反思。但你必须测量才能确定。
interface IHasNameAndAge
{
string Name { get; }
int Age { get; }
}
class A : IHasNameAndAge
{
public string Name { get; set; }
public int Age { get; set; }
string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B : IHasNameAndAge
{
public string Name { get; set; }
public int Age { get; set; }
string Location { get; set; }
public A(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
void Output(IHasNameAndAge obj)
{
Console.WriteLine(obj.Name + " is " + obj.Age);
}