将混凝土浇筑到通用型?
我正在尝试编译以下代码:
public class BaseRequest where TResponse : BaseResponse {} public class BaseResponse {} public class FooRequest : BaseRequest {} public class FooResponse : BaseResponse {} ... public TResponse MakeRequest(BaseRequest request) where TResponse : BaseResponse { }
我希望我可以调用MakeRequest(new FooRequest())
并将返回值作为FooResponse
。 被调用者不必知道FooRequest
并且可以将其传递给另一个处理程序。 签名工作正常,但我无法实现MakeRequest
方法。 如果我实现它像:
public TResponse MakeRequest(BaseRequest request) where TResponse : BaseResponse { FooRequest fooRequest = request as FooRequest; if (fooRequest != null) // if I can handle the request, handle it { return new FooResponse(...); // *** } BarRequest barRequest = request as BarRequest; if (barRequest != null) { return new BarResponse(...); } else // otherwise, pass it on to the next node { // maybe it will handle a BazRequest, who knows return nextNode.MakeRequest(request); } }
但***
行不会编译,因为编译器不知道FooResponse
是一个TResponse
。 我知道这是因为它在FooRequest
指定。 有没有办法解决这个问题,而不涉及讨厌的reflection(在这种情况下,我宁愿返回BaseResponse
)?
谢谢。
更新 :我正在使用generics来强制执行返回类型,因此调用站点确切地知道会发生什么。 在这里返回BaseResponse
要容易BaseResponse
,但是它将具体的返回类型的负担放到了调用者而不是请求处理程序(当然知道关于输入的所有内容)。
正如我在评论中所说,我怀疑你做错了。 这看起来像滥用generics。
也就是说,你告诉编译器“我知道比你更多的类型信息”的方式是通过强制转换。
var response = new FooResponse(...); return (TResponse)(object)response;
转换为对象然后转向TResponse告诉编译器“我知道从响应到TResponse有一个标识,拆箱或引用转换”。 如果你错了,你会在运行时得到一个例外。
在我看来,您应该从非generics版本BaseRequest
派生您的BaseRequest
类,然后将您的函数编写为:
public BaseResponse MakeRequest(BaseRequest request)
这似乎是正确的方法,因为你甚至没有提到函数内部的类型。
在我看来,仿制药只是作为语法糖。 以你的方式编写函数所能获得的是能够编写:
FooResponse r = MakeRequest(new FooRequest(...))
而不是这个:
FooResponse r = (FooResponse)MakeRequest(new FooRequest(...))
所以好处并不大。 事实上,你被自己的代码搞糊涂了,以至于你无法看到丢失的东西是强制转换意味着代码可能比非generics方式更不清楚。
哦,你的方法的另一个缺点是你将失去做的能力:
var requests = new List { new FooRequest(), new BarRequest() }; var responses = new List (); foreach(var request in requests) { responses.Add(MakeRequest(request)); }
或者你可以做的是:
public BaseResponse MakeRequest(BaseRequest request) { /* thing that does the work */ } public TResponse MakeRequest(BaseRequest request) { // Just for the nice syntax return (TResponse)MakeRequest(request); }
但这看起来真的很复杂。 无论如何,我会让你反思
上述就是C#学习教程:将混凝土浇筑到通用型?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/950577.html