没有赋值的隐式转换?
保留问题 - 请参阅底部的编辑
我正在开发一个小型函数库,基本上是通过隐藏基本的圈复杂度来提供一些可读性。该提供程序称为 Select
(带有一个名为 Select
的帮助器工厂),用法类似于
public Guid? GetPropertyId(...)
{
return Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
.Or(IGuessWeCanTryThisTooIfWeReallyHaveTo(...))
//etc.
;
}
,库将处理短路等问题。还添加了从 Select
到 T
的隐式转换,因此我可以编写
public Guid GetPropertyId(...)
{
ServiceResult result = Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...));
return result.Id;
}
我真正想要做的是在不赋值的情况下隐式转换到 T :
public Guid GetPropertyId(...)
{
return
//This is the part that I want to be implicitly cast to a ServiceResult
Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
//Then I want to access this property on the result of the cast
.Id;
}
但是,指定的语法不起作用 - 我必须将其分配给变量,或显式转换它。有没有办法获得隐式强制转换?
编辑
我想做的是:
class Foo {
public int Fuh { get; set; }
}
class Bar {
private Foo _foo;
public static implicit operator Foo (Bar bar)
{
return bar._foo;
}
}
//What I have to do
Foo bar = GetABar();
DoSomethingWith(bar.Fuh);
//What I want to do
DoSomethingWith(GetABar().Fuh);
Preserved question - see Edit at the bottom
I'm working on a small functional library, basically to provide some readability by hiding basic cyclomatic complexities. The provider is called Select<T>
(with a helper factory called Select
), and usage is similar to
public Guid? GetPropertyId(...)
{
return Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
.Or(IGuessWeCanTryThisTooIfWeReallyHaveTo(...))
//etc.
;
}
and the library will take care of the short circuiting, etc. I also added an implicit conversion from Select<T>
to T
, so I can write
public Guid GetPropertyId(...)
{
ServiceResult result = Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...));
return result.Id;
}
What I'd really like to be able to do is an implicit conversion to T without assignment:
public Guid GetPropertyId(...)
{
return
//This is the part that I want to be implicitly cast to a ServiceResult
Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
//Then I want to access this property on the result of the cast
.Id;
}
However, the specified syntax doesn't work - I have to either assign it to a variable, or explicitly cast it. Is there a way to get an implicit cast inline?
EDIT
What I want to do is this:
class Foo {
public int Fuh { get; set; }
}
class Bar {
private Foo _foo;
public static implicit operator Foo (Bar bar)
{
return bar._foo;
}
}
//What I have to do
Foo bar = GetABar();
DoSomethingWith(bar.Fuh);
//What I want to do
DoSomethingWith(GetABar().Fuh);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您只想处理特定类型,则可以添加包装方法或属性。如果 myThing 有一个类型为“Bar”的方法,该方法返回“self.internalThing.Bar”,那么人们可能会产生一种错觉,即返回 myThing 的表达式实际上返回了其包装类型的表达式。然而,我知道在一般情况下没有办法做到这一点。对于未来的 C# 和 VB 版本来说,允许“包装”类中的一个属性可能很有用,但我知道在现有的语言中没有办法做到这一点。
If you are only going to be dealing with specific types, you could add wrapper methods or properties. If myThing has a method of type "Bar" which returns "self.internalThing.Bar", then one could maintain the illusion that that an expression returning a myThing was really returning an expression of its wrapped type. I know of no way to do that in the general case, however. It might be useful for future C# and VB versions to allow one property in a class to be "wrapped", but I know of no way to do that in the language as it exists.
你尝试过吗
Did you try
我想我看到了你的问题。
Or
返回Select
,而不是ServiceResult
,因此编译器无法知道您期望获取Id<来自
ServiceResult
对象的 /code> 属性。怎么可能呢?它是否应该看到没有Select.Id
属性并开始寻找可能的隐式转换以查看其中之一是否具有名为Id
的属性?以下是您的一些选择:
或
或
I think I see your problem.
Or
returns aSelect
, not aServiceResult
, so there's no way that the compiler could know that you expect to get theId
property from aServiceResult
object. How could it? Should it see that there is noSelect.Id
property and start looking for possible implicit conversions to see if one of them has a property calledId
?Here are a few of your choices:
or
or
如果你想将转换为 guid 内联,你可以做一个扩展方法,
我认为它并没有真正添加一些东西,但在我的观点中更好读。
If you want put the conversion to guid inline you can do a extension method
i don't think it really add something, but in my pov is better to read.
我认为这是不可能的;必须有某种操作员发挥作用才能导致铸造。编译器/运行时不能只是“知道”您希望它是 T 类型,您必须以某种方式指示它这样做。
I don't think that is doable; some kind of operator has to come into play to cause the casting. The compiler/runtime can't just 'know' that you want it to be of type T, you have to somehow instruct it to do so.
是的,有两种方法可以做到这一点。
第一个叫做“继承”。你可以这样做:
这告诉编译器“当你查找 Bar 的成员时,也查找 Blah 的成员”。它还告诉编译器 Bar 的实例可以隐式转换为 Blah 类型。
Blah 可以是类或接口类型。
第二个称为“类型参数的类和接口约束”。您向编译器这样提示:
现在 t 可以隐式转换为 Blah,并且 t 上的成员访问将包括 Blah 上声明的成员。
同样,Blah 可以是接口或类类型。
C# 中没有其他方法可以影响 Bar 类型上的成员查找,以便在 Blah 类型上声明添加的成员,其中 Bar 可隐式转换为 Blah。
Yes, there are two ways to do that.
The first is called "inheritance". You do it like this:
That tells the compiler "when you're looking up members of Bar, look up members of Blah too". It also tells the compiler that instances of Bar are implicitly convertible to type Blah.
Blah can be either a class or an interface type.
The second is called "class and interface constraints on type parameters". You hint to the compiler like this:
Now t is implicitly convertible to Blah, and member access on t will include members declared on Blah.
Again, Blah can be an interface or class type.
There are no other ways in C# to affect member lookup on a type Bar such that the added members are declared on a type Blah, where Bar is implicitly convertible to Blah.
虽然隐式转换确实在这里不起作用,但通过向
Select
添加Value
属性,您可能会比显式转换做得更好。那么您的表达式将是Select.[operations].Value.Id
,读起来仍然相当不错。While it's true that an implicit cast won't work here, you could possibly do better than an explicit cast by adding a
Value
property toSelect<T>
. Then your expression would beSelect.[operations].Value.Id
, which still reads reasonably well.