我们今天在工作中讨论了用例,其中您有类似以下代码的内容:
using System;
namespace test
{
class Program
{
public class A
{
public void Foo()
{
Console.WriteLine("This is A.");
}
}
public class B
{
public void Foo()
{
Console.WriteLine("This is B");
}
}
public static void Test(object obj)
{
if (obj is A a)
{
a.Foo();
}
else if (obj is B b)
{
b.Foo();
}
}
static void Main(string[] args)
{
Test(new A());
}
}
}
然后,我们讨论了如何通过抽象这样的行为(或使用接口,取决于在上下文中哪种效果最佳)来删除“ is”关键字:
using System;
namespace test
{
class Program
{
public abstract class Base
{
public abstract void Foo();
}
public class A : Base
{
public override void Foo()
{
Console.WriteLine("This is A.");
}
}
public class B : Base
{
public override void Foo()
{
Console.WriteLine("This is B");
}
}
public static void Test(Base obj)
{
obj.Foo();
}
static void Main(string[] args)
{
Test(new A());
}
}
}
因此,从那里开始,我们一群人试图弄清楚在哪种情况下使用“ is”关键字确实是合理的。我们可以提出的所有示例均被排除,因为它们来自其他代码气味。
我在网上做了一些研究以寻找答案,但是大多数网站只提供定义和如何使用关键字,但找不到任何可以引用与该关键字有关的“良好做法”的资料。
总而言之,我的问题是,在哪些情况下(如果有的话)使用“ is”关键字是合理的(必要/更优雅)?
编辑:更多信息需要澄清。在很多情况下,即使不是大多数关键字/声明/指令,也存在使用有意义的上下文以及其他使用不合理的上下文。
例如,try
,catch
,throw
非常适合当您需要对程序运行时出现的异常情况(例如尝试除法)做出响应时减零。但是,大多数程序员都同意将它们用于控制流是一个坏主意。
出于同样的考虑,goto
可用于开关或嵌套循环中,这是通常接受的用法。但是,如果您开始使用goto
在代码中跳来跳去,那么再次被大多数程序员认为是一个坏主意。
因此,我想确定is
的哪些用例将被大多数程序员拒绝,哪些用例将被大多数程序员拒绝?
答案 0 :(得分:2)
一切对某人来说都是代码的味道,有些比其他东西更有趣。
检查对象是否与给定类型兼容,或(以 C#7.0)针对模式测试表达式。
寻求is
的合法使用就像要求合法使用水一样。它永无止境,所有人都可以整日辩论……如果您某人竭尽全力证明一切都是气味,那么您将永远不会获胜。
但是,我们所知道的是。如果您需要检查对象是否与给定类型兼容,那么您有一个合法的用例,以故事。
考虑事件和发送者参数。
考虑基本类型列表。
<insert oodles of more list items here>
BCL示例
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
{
if (source == null) throw Error.ArgumentNull("source");
return OfTypeIterator<TResult>(source);
}
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source)
{
foreach (object obj in source)
{
if (obj is TResult) yield return (TResult)obj;
}
}