Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用方法时指定子类(或任何类)作为返回类型_C#_Generics_Design Patterns - Fatal编程技术网

C# 调用方法时指定子类(或任何类)作为返回类型

C# 调用方法时指定子类(或任何类)作为返回类型,c#,generics,design-patterns,C#,Generics,Design Patterns,基于我下面的类,我应该如何设置应用方法,以便在调用它时,可以指定所需的BaseResult返回类型 目的是让调用代码知道Apply返回的子类(实现BaseResult)是什么(同样,考虑到调用Apply来自IRequest,而不是它的实现) 条件是: IRequest的实现可能有很多种 BaseResult可能有许多实现 代码: void Main() { // For example purpose, let's pretend 'myreq' is retrieved from

基于我下面的类,我应该如何设置
应用
方法,以便在调用它时,可以指定所需的
BaseResult
返回类型

目的是让调用代码知道Apply返回的子类(实现
BaseResult
)是什么(同样,考虑到调用Apply来自
IRequest
,而不是它的实现)

条件是:

  • IRequest的实现可能有很多种
  • BaseResult可能有许多实现
代码

void Main()
{
    // For example purpose, let's pretend 'myreq' is retrieved from reflection. So, there's no way I would know it's type of MyRequest. And there will be many other implementations of IRequest.
    var req = new MyRequest();

    var request = (IRequest)req;

    // How should I setup Apply method so that when I call the method, I can specify what BaseResult return type that I want?
    // In this example, I would like Apply method to return Result type, which inherits from BaseResult.
    var res = req.Apply<Result>();
}

// Define other methods and classes here
public interface IRequest
{
    string GetValue();
    T Apply<T>() where T : BaseResult;
}

public class MyRequest : IRequest
{
    // How should I setup Apply method to allow returning any BaseResult I want? Each IRequest implementation of Apply method may return different BaseResult type.
    public T Apply<T>() where T : BaseResult
    {
        // Doesn't work here
        // Can't implicitly convert type BaseResult to T
        return (BaseResult) new Result();
    }

    public string GetValue() { return string.Empty; }
}

public class Result : BaseResult
{
    public string Message { get; set;}
}

public class AnotherResult : BaseResult
{
    public string Message { get; set; }
}

public class BaseResult
{
}
void Main()
{
//例如,让我们假设“myreq”是从反射中检索到的。因此,我无法知道它是MyRequest的类型。而且还有许多其他的IRequest实现。
var req=new MyRequest();
var请求=(IRequest)请求;
//我应该如何设置Apply方法,以便在调用该方法时,可以指定所需的BaseResult返回类型?
//在本例中,我希望应用方法返回从BaseResult继承的结果类型。
var res=req.Apply();
}
//在此处定义其他方法和类
公共接口IRequest
{
字符串GetValue();
T Apply(),其中T:BaseResult;
}
公共类MyRequest:IRequest
{
//我应该如何设置Apply方法以允许返回我想要的任何BaseResult?Apply方法的每个IRequest实现可能返回不同的BaseResult类型。
public T Apply(),其中T:BaseResult
{
//这里不行
//无法将类型BaseResult隐式转换为t
返回(BaseResult)新结果();
}
公共字符串GetValue(){return string.Empty;}
}
公共类结果:BaseResult
{
公共字符串消息{get;set;}
}
公共类另一个结果:BaseResult
{
公共字符串消息{get;set;}
}
公共类基结果
{
}

您能否将
应用的类型限制为具有默认构造函数

public T Apply<T>() where T : BaseResult, new()
{
    //you could put settable properties on BaseResult
    //(or similar interface) and set them here, as well.
    return new T();
}
public T Apply(),其中T:BaseResult,new()
{
//您可以将可设置属性放在BaseResult上
//(或类似接口)并在此处设置它们。
返回新的T();
}
这还需要您在接口上指定约束:

public interface IRequest
{
    string GetValue();
    T Apply<T>() where T : BaseResult, new();
}
公共接口IRequest
{
字符串GetValue();
T Apply(),其中T:BaseResult,new();
}

您可以将
Apply
的返回类型更改为
BaseResult

public interface IRequest
{
    string GetValue();
    BaseResult Apply<T>() where T : BaseResult;
}

public class MyRequest : IRequest
{
    public BaseResult Apply<T>() where T : BaseResult
    {
        return new Result();
    }

    public string GetValue() { return string.Empty; }
}
公共接口IRequest
{
字符串GetValue();
BaseResult Apply(),其中T:BaseResult;
}
公共类MyRequest:IRequest
{
public BaseResult Apply(),其中T:BaseResult
{
返回新结果();
}
公共字符串GetValue(){return string.Empty;}
}
Edit:我认为您无论如何都需要使用此解决方案进行类型转换,但需要在调用代码中进行转换。所以这并不能真正解决问题


编辑2:实际上,返回泛型类型似乎有这个特殊的目的——避免在调用代码中强制转换。如果在调用Apply方法的代码中已知所需的类型,那么是否确实有必要将新实例强制转换为T

public T Apply<T>() where T : BaseResult
{
    var newInstance = new Result();
    return newInstance as T;
}
public T Apply(),其中T:BaseResult
{
var newInstance=新结果();
将newInstance返回为T;
}

您能否将
应用的类型约束为需要
新建()
?您的代码不是泛型的。如果您调用了
Apply
?你会将一个
结果
转换为另一个运行时会失败的
结果,@DStanley,这就是为什么我在这里,寻求其他人对我的问题的想法和解决方案……)@stack247但是您在方法中显式地创建了一个
结果
。它是否应该创建一个
T
?如果
T
另一个结果
@Enigmativity
T
在我的调用中不是
另一个结果
,则在运行时该操作将失败。即使是这样,操作符
as
在运行时也不会失败。如果返回的对象不是
T
的类型,它只会返回
null
。这是一个奇怪的签名-
public BaseResult Apply(),其中T:BaseResult
T
在这里没有任何用处。我想它仍然会限制调用者“请求”一些不是从
BaseResult
派生的类型。虽然我同意这是一个奇怪的泛型应用程序。@DmitryRotay是的,我的目的是让调用代码知道
BaseResult
的哪个子类(实现
Apply
)正在返回(再次考虑到从
IRequest
调用
Apply
,而不是它的实现)@DmitryRotay从您的解决方案中,我还可以执行
public BaseResult Apply()
。然后调用代码必须使用反射来查看
IRequest
的具体实现返回的
BaseResult
类型。然后,使用该信息强制转换返回对象。你觉得怎么样?@stack247我想这行不通
IRequest
返回
BaseResult
。在调用
Apply
方法之前,您不知道它返回什么具体类型。事实上,我的观点是,当前签名假设您已经知道希望它返回的类型(您将其作为类型参数传递),所以所有这些带有泛型的把戏都没有什么意义。我想你应该详细说明一下你想要达到的目标。也许有更好的方法。您提出的解决方案是返回新的
T
。如果对象类型为
BaseResult
,我应该如何返回该对象而不是新的
T