如何对具有相同成员的不同类型参数使用相同的函数?

本文关键字:类型参数 函数 成员 | 更新日期: 2023-09-27 18:07:57

下面是示例代码,我定义了两个类。我如何使用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.
}

如何对具有相同成员的不同类型参数使用相同的函数?

你必须:

  1. 使用反射来获取属性(如果不存在则抛出)
  2. 有一个共同的接口,如INamed有一个字符串Name属性,这两个类都实现
  3. 声明一个局部变量为dynamic,并使用它来访问Name属性(但实际上这与#1相同,因为动态调度将仅仅使用反射来获取Name属性)。

您可以利用dynamic绕过编译器,它在运行时检查类型,因此您不需要强制转换:

void Output(dynamic obj)
{
    Console.WriteLine(obj.Name); 
}

你应该声明一个接口来描述这两个类的公共部分:

interface I
{
    string Name { get; set; }
    int Age { get; set; }
}

然后在AB中实现它:

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); 
}

您可以使用dynamic、反射或继承。或者你可以复制这个方法并利用方法重载

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);
}

您需要为这两个类创建一个公共接口,以便编译器知道这两个类可以提供某些特性(在您的例子中是Name和age):

    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);
    }

在您的例子中- B不继承A,因此您不能将B强制转换为A。

将B改为继承A,如

class B : A
{
...
}

还要考虑你想在B类的A()方法中完成什么。如果是继承的,则可能不需要两次声明相同的成员。

你可以这样做:

if ( obj.GetType() == typeof( A ) )
{
    Console.WriteLine(((A)obj).Name);
}
else if ( obj.GetType() == typeof( B ) )
{
    Console.WriteLine(((B)obj).Name);
}