与 F# 匹配表达式最接近的 C# 等效项?
我的情况是,我的很多类都是众所周知但不同类型的无序对象的容器,例如容器可能如下所示:
public class Container
{
public A A { get; private set; }
public B B { get; private set; }
public C C { get; private set; }
public bool StoreIfKnown(object o)
{
// TODO...
}
}
所以如果 o
的类型为 A
它应该存储在 A
属性中,在 B
属性中键入 B
等等。
在 F# 中,StoreIfKnown
方法可以编写如下内容(请原谅语法错误,我的 F# 不太好而且很生疏):
match o with
| ?: A a -> A <- a; true
| ?: B b -> B <- b; true
| ?: C c -> C <- c; true
| _ -> false
但在 C# 中,唯一的方法似乎相当冗长:
if (o is A)
{
this.A = (A)o;
return true;
}
if (o is B)
{
this.B = (B)o;
return true;
}
// etc.
return false;
我可以使用 as
关键字来避免测试/转换模式,这会更快,但更冗长。
在 C# 中有什么优雅的方法可以做到这一点吗?
I'm in the situation where a lot of my classes are containers of well-known but unordered objects of different types, e.g. a container may look as follows:
public class Container
{
public A A { get; private set; }
public B B { get; private set; }
public C C { get; private set; }
public bool StoreIfKnown(object o)
{
// TODO...
}
}
So if o
is of type A
it should be stored in the A
property, type B
in the B
property and so on.
In F# the StoreIfKnown
method could be written something like the following (excuse the syntax errors, my F# is not great and quite rusty):
match o with
| ?: A a -> A <- a; true
| ?: B b -> B <- b; true
| ?: C c -> C <- c; true
| _ -> false
But in C# the only way seems to be the rather verbose:
if (o is A)
{
this.A = (A)o;
return true;
}
if (o is B)
{
this.B = (B)o;
return true;
}
// etc.
return false;
I could do it with the as
keyword to avoid the test/cast pattern which would be faster, but is even more verbose.
Is there any elegant way to do this in C#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以在“o”和辅助类上编写一个扩展方法,以启用类似的编程模型,
但要小心,不要在这里做太多类似 DSL 的黑客行为,以免您最终得到一个只有您理解的 API。
另请参见
You could author an extension method on 'o' and helper classes to enable a programming model like
But be wary of doing too much DSL-like hackery here, lest you end up with an API only you understand.
See also
http://blogs.msdn.com/lucabol/archive/2008/07/15/a-c-library-to-write-functional-code-part-v-the-match-operator.aspx
它不像 Brian 的解决方案那么漂亮,但这不需要定义新的 DSL。您会注意到重复了以下代码:
将该模板拉入其自己的方法中很容易,结果如下所示:
如果您正在使用引用类型,则可以通过以下调整来利用类型推断:
Its not as nifty as Brian's solution, but this doesn't require defining a new DSL. You'll notice your repeating the following code:
Its easy enough to pull that template into its own method, resulting in something like this:
If you're working with reference types, you can take advantage of type inference with the following adjustments:
我一直在玩一个小匹配构建器(灵感来自 Brian 的回答),它允许类型检查、保护子句以及从整个事情返回结果。它使用类型推断,因此您唯一需要指定类型的地方就是您真正想要的地方。
因此,想象类型
C
有一个IsActive
属性,我们希望该属性为true
,它看起来像这样:我认为这是非常可读的,特别是因为它允许在实际匹配之前针对派生类型运行谓词,这是我确实需要的。
该代码相当冗长,因为它需要在后台使用许多部分指定的构建器类来允许类型推断工作,所以我不能真正将其发布在这里。但如果有人感兴趣,请在评论中告诉我,我会将其贴在我的博客上并在此处放置链接。
I've been playing around with a little match builder (inspired by Brian's answer) which allows type checking, guard clauses, and returning of a result from the whole thing. It uses type inference so the only place you need to specify a type is where you actually want to.
So, imagining type
C
has anIsActive
property which we want to betrue
, it would look something like this:Which I think is pretty readable, especially as it allows a predicate to be run against the derived type before actually matching which is something I do need.
The code is quite lengthy as it needs a number of partially-specified builder classes in the background to allow the type inference to work, so I can't really post it here. But if anyone's interested let me know in the comments and I'll stick it up on my blog and put a link here.
Bart de Smet 曾经对模式匹配感到疯狂,从 此处(一直到第 8 部分)。如果您设法读完所有这些内容,那么 C# 中的模式匹配就不会有任何问题了。如果有的话,stackoverflow 可能无法回答:)
Bart de Smet once went crazy with pattern matching, starting here (goes all the way up to part 8). If you ever manage to get through all this content there shouldn't be any questions left to pattern matching in C#. If there are, they probably cannot be answered by stackoverflow :)
截至 2016 年 8 月和 C# 7.0 预览版,对模式匹配的支持有限。您可以尝试使用 Visual Studio “15”预览 4。
根据 MSDN 博客,您可以在两个地方使用模式:
在是表达式的右侧
在 switch 语句中的 case 子句中
可能的模式有:
我未安装的 输入相同Visual Studio 15,所以我不确定我是否正确重写了您的代码,但应该相差不远:
As of August 2016 and preview of C# 7.0, there is a limited support for pattern matching. You can try if by using Visual Studio “15” Preview 4.
According to the MSDN blog, you can use patterns in two places:
on the right-hand side of is expressions
in the case clauses in switch statements
Possible patterns are:
I didn't install Visual Studio 15, so I'm not sure I rewrote your code correctly, but it should not be far off: