子类多次重写ToString方法问题及代码标识符错误求助
首先,你遇到的Identifier expected错误完全是因为语法写错了——animalList[i].((Animal)animalObj).ToString()这种写法不符合C#的语法规则,编译器根本不知道那个点后面要识别什么标识符。我们一步步来解决这个问题,同时解答你关于指定调用子类ToString的疑问。
1. 先修复当前的语法错误
你写的代码里,animalList[i]应该是你要操作的Animal实例(假设animalList是List<Animal>类型),而方法参数里的animalObj在这里的用法完全不对。如果你想强制转换animalList[i]到某个子类,正确的写法应该是:
// 强制转换为Mammal后调用ToString ((Mammal)animalList[i]).ToString(); // 或者强制转换为Insect ((Insect)animalList[i]).ToString();
不过要注意:这种写法只有当animalList[i]确实是对应子类的实例时才会正常运行,否则会抛出InvalidCastException异常。
2. 为什么直接调用.ToString()就能正常运行?
这是C#多态的特性:只要你的Mammal和Insect子类都正确重写了ToString方法(比如用override关键字),那么通过Animal类型的引用(也就是animalList[i])调用.ToString()时,会自动执行对应子类的实现。这是面向对象编程里最推荐的方式,代码简洁且符合设计原则,不需要手动指定类型。
举个例子,假设你的子类是这么写的:
public class Mammal : Animal { public override string ToString() { return "这是哺乳动物"; } } public class Insect : Animal { public override string ToString() { return "这是昆虫"; } }
那么不管animalList[i]是Mammal还是Insect,直接调用animalList[i].ToString()都会返回对应的子类字符串。
3. 如果确实需要手动指定调用某个子类的ToString方法
如果你有特殊场景(比如需要跳过多态,或者明确指定类型),可以用以下几种方式:
方式一:模式匹配(推荐,C# 7.0+支持)
通过类型检查直接转换,不会抛出异常:
if (animalList[i] is Mammal mammal) { taskArray[i] = mammal.ToString(); // 明确调用Mammal的ToString } else if (animalList[i] is Insect insect) { taskArray[i] = insect.ToString(); // 明确调用Insect的ToString } else { taskArray[i] = animalList[i].ToString(); // 默认调用Animal的ToString }
方式二:使用as关键字
as关键字会尝试转换,失败时返回null,所以需要判空:
Mammal mammal = animalList[i] as Mammal; if (mammal != null) { taskArray[i] = mammal.ToString(); } else { Insect insect = animalList[i] as Insect; if (insect != null) { taskArray[i] = insect.ToString(); } else { taskArray[i] = animalList[i].ToString(); } }
方式三:根据传入的animalObj类型来决定调用(针对你的方法参数)
看你的方法里有Animal animalObj参数,如果你想根据animalObj的类型,把animalList[i]转成对应子类调用ToString,可以这么写:
Type targetType = animalObj.GetType(); if (targetType == typeof(Mammal) && animalList[i] is Mammal mammal) { taskArray[i] = mammal.ToString(); } else if (targetType == typeof(Insect) && animalList[i] is Insect insect) { taskArray[i] = insect.ToString(); } else { taskArray[i] = animalList[i].ToString(); }
不过要注意:如果animalObj是Animal基类的实例(而不是子类),targetType会是Animal,这时候就会走默认分支。
总结
绝大多数情况下,直接利用多态调用animalList[i].ToString()就是最优解——既简洁又符合面向对象的设计思想。只有在特殊业务需求下,才需要手动判断类型来指定调用子类的方法。
内容的提问来源于stack exchange,提问作者adde09

