这里有两个简单的类:
class Abc { public int x; }
class Bcd { public int y; }鉴于obj是object类型,下面是两个具有某些特征的Abc或Bcd测试示例:
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);什么是处理这种模式的好方法:
if (obj is Abc && (obj as Abc).SomePropertyOrMethod && ...一种方法是Is扩展方法:
public static bool Is<T>(this object obj, Func<T, bool> pred) where T : class
=> (obj is T) && pred(obj as T);这样,上面的例子就可以写成:
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);这样,(obj as ...)表达式就不会重复。
有没有其他方法来实现这种模式?
这个pattern matching proposal似乎可以很好地处理这个问题(参见8.1节)。
发布于 2015-08-03 04:40:05
此外,这是对as的滥用。
另一种方法是声明一个变量:
var abc = obj as Abc;
if (abc != null && abc.x > 0 && Math.Pow(abc.x, 2) > 100)
Console.WriteLine(123);看起来很简单。我看不出有什么问题。
也就是说,扩展方法方法在您不能轻松声明变量的地方很有用,例如在某些查询或深度嵌套的表达式中。这通常是不可取的,但有时也会发生。
发布于 2015-08-03 04:41:11
我不确定什么是最好的/最坏的,但如果转换失败,(obj as Abc).x可能会在NullReferenceException中结束。我看到的一种方法是分解条件检查,如下所示:
Abc a = obj as Abc;
if (a != null && a.x > 0 && Math.Pow(a.x, 2) > 100)
Console.WriteLine(123);这样,就不需要检查条件obj is Abc了,因为只有在a != null强制转换成功时,true才是obj as Abc。
发布于 2015-08-03 05:27:59
添加一些静态检查:
public static bool Is<T, TBase>(this TBase obj, Func<T, bool> pred)
where TBase : class
where T : class, TBase
{
var t = obj as T;
return t != null && pred(t);
}像这样使用:
TypeBase obj;
...
if (obj.Is((TypeA obj) => ...))https://stackoverflow.com/questions/31776304
复制相似问题