模式的方法:"if(obj是Abc &&(obj as Abc)......)"

dha*_*ech 3 c#

这是两个简单的类:

class Abc { public int x; }
class Bcd { public int y; }
Run Code Online (Sandbox Code Playgroud)

鉴于它obj是类型object,这里有几个测试AbcBcd具有某些特征的例子:

if (obj is Abc && (obj as Abc).x > 0 && Math.Pow((obj as Abc).x, 2) > 100)
    Console.WriteLine(123);

if (obj is Bcd && (obj as Bcd).y > 0 && Math.Pow((obj as Bcd).y, 2) > 100)
    Console.WriteLine(234);
Run Code Online (Sandbox Code Playgroud)

处理这种模式的好方法是什么:

if (obj is Abc && (obj as Abc).SomePropertyOrMethod && ...
Run Code Online (Sandbox Code Playgroud)

一种方法是Is扩展方法:

public static bool Is<T>(this object obj, Func<T, bool> pred) where T : class
    => (obj is T) && pred(obj as T);
Run Code Online (Sandbox Code Playgroud)

有了这个,上面的例子可以写成:

if (obj.Is<Abc>(abc => abc.x > 0 && Math.Pow(abc.x, 2) > 100))
    Console.WriteLine(123);

if (obj.Is<Bcd>(bcd => bcd.y > 0 && Math.Pow(bcd.y, 2) > 100))
    Console.WriteLine(234);
Run Code Online (Sandbox Code Playgroud)

这样(obj as ...)就不再重复表达了.

这种模式还有其他方法吗?

这种模式匹配提议似乎可以很好地处理这个问题(参见第8.1节).

usr*_*usr 5

我觉得这需要一件简单的事情并使其变得复杂.此外,扩展导致的名称空间污染object也不是很好.此外,这是滥用as.这应该是投掷演员(例如((Abc)obj)),因为我们期望演员总是成功.投掷演员有一个断言和内置的一个很好的例外.它正在记录这一预期会成功的事实.

另一种方法是声明一个变量:

var abc = obj as Abc;
if (abc != null && abc.x > 0 && Math.Pow(abc.x, 2) > 100)
    Console.WriteLine(123);
Run Code Online (Sandbox Code Playgroud)

看起来很简单.我认为没有问题.

也就是说,扩展方法方法在您无法轻松声明变量的地方非常有用,例如在某些查询或深层嵌套表达式中.这通常是不受欢迎的,但有时会发生.

  • @dharmatech失败的演员将被一个`is`检查看守,就像你现在正在做的那样.只需用`(Abc)`替换`as`即可. (2认同)