2016-04-13 89 views
1

指定子類(或任何類)作爲返回類型時應該如何設置Apply方法,以便當我調用它時,可以指定我想要的返回類型BaseResult當調用方法

目的是讓調用代碼知道是什麼子類(實施BaseResult),該應用將返回(再次,考慮到從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 
{ 
} 
+0

可以約束類型應用''需要一個'新的()'? – AGB

+0

您的代碼不是通用的。如果你叫'Apply ',怎麼辦?你會將一個'Result'投射到'AnotherResult',這在運行時會失敗, –

+0

@Dananley,這就是爲什麼我在這裏,尋求其他人的想法和解決我的問題.. :) – stack247

回答

0

在你的應用方法,鑄就新的實例爲T.

public T Apply<T>() where T : BaseResult 
{ 
    var newInstance = new Result(); 
    return newInstance as T; 
} 
+0

如果'T'是'AnotherResult',這將在運行時失敗。 – Enigmativity

+0

@Enigmativity在我的電話中'T'不是'AnotherResult'。即使這樣,運算符as也不會在運行時失敗。如果返回的對象不是'T'的類型,它只會返回'null'。 – stack247

+0

@ stack247 - 然後通用的點是什麼? – Enigmativity

1

你能約束的Apply<T>類型有一個默認的構造函數?

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 interface IRequest 
{ 
    string GetValue(); 
    T Apply<T>() where T : BaseResult, new(); 
} 
+0

您提出的解決方案是返回新的「T」。如果我有'BaseResult'的對象類型,我應該如何返回該對象而不是新的'T'? – stack247

0

您可以更改Apply<T>返回類型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; } 
} 

編輯:想象一下,您需要使用此解決方案進行類型轉換,而不是在調用代碼中。所以它並不能真正解決問題。

編輯2:實際上,它看起來像返回泛型類型服務於此特定用途 - 以避免在調用代碼中投射。鑑於所需的類型在代碼Apply中已知,是否真的有必要?

+1

這是一個奇怪的簽名 - '公共BaseResult應用()其中T:BaseResult' - 'T'在這裏沒有做任何有用的事情。 – Enigmativity

+0

嗯,我想它仍然限制呼叫者「請求」一些不是從'BaseResult'派生的類型。雖然我同意這是一種奇怪的泛型應用。 –

+0

@DmitryRotay是的,我的目的是讓調用代碼知道'Apply'正在返回的子類(BaseResult'的實現)(再次,考慮到從'IRequest'調用'Apply',而不是執行它)。 – stack247

相關問題