如何在C#中实现类似JavaScript的通用对象传参功能
C#实现类似JS通用传参调用的方案
可以实现,以下是三种常用实现方式,优先推荐接口方案符合C#强类型最佳实践。
方案1:使用公共接口(强类型推荐方案)
C#作为强类型语言,最规范的实现方式是抽象公共属性为接口,所有需要传入的类实现该接口即可:
// 定义公共接口 public interface IHasName { string Name { get; } } // 实现接口的Human类 public class Human : IHasName { public string Name { get; set; } = "John"; } // 实现接口的Cat类 public class Cat : IHasName { public string Name { get; set; } = "Garfield"; } // 统一的ShowName方法 public void ShowName(IHasName character) { Console.WriteLine($"My name is: {character.Name}"); } // 调用示例 var character1 = new Cat(); var character2 = new Human(); ShowName(character1); ShowName(character2);
方案2:使用dynamic关键字(最接近JS的弱类型写法)
如果不想定义接口,可以用dynamic关键字跳过编译期类型检查,行为和JS弱类型完全一致:
public class Human { public string Name { get; set; } = "John"; } public class Cat { public string Name { get; set; } = "Garfield"; } // 参数用dynamic接收任意类型 public void ShowName(dynamic character) { Console.WriteLine($"My name is: {character.Name}"); } // 调用方式和JS完全一致 var character1 = new Cat(); var character2 = new Human(); ShowName(character1); ShowName(character2);
注意:该方案编译期不会检查属性是否存在,如果传入的对象没有Name属性,会在运行时抛出异常
方案3:反射实现(适合无法修改原有类定义的场景)
如果你不能修改Human、Cat类的代码,无法给它们加接口,可以用反射动态读取Name属性:
public void ShowName(object character) { // 反射获取Name属性 var nameProperty = character.GetType().GetProperty("Name"); if (nameProperty == null) { throw new ArgumentException("传入对象不包含Name属性", nameof(character)); } string name = nameProperty.GetValue(character)?.ToString(); Console.WriteLine($"My name is: {name}"); }
方案对比
- 接口方案:编译期类型安全、运行效率最高,是C#开发的首选方案
- dynamic方案:写法最简洁,和JS行为一致,但无编译校验,仅适合快速开发的内部场景
- 反射方案:兼容性最好,不需要修改原有类,但性能最低,需要额外处理属性不存在的异常情况
内容的提问来源于stack exchange,提问作者Scoppex
相关产品推荐
相关产品推荐

