2012-06-29 205 views
3

我試圖完成的是有兩個類,一個非泛型和一個泛型。隱藏基類的屬性

我需要一個非通用類,因爲我計劃在List<T>

插入這個類的對象,並把它們插入下面的代碼

// Non-generic 
public class Response 
{ 
    public object Value { get; } 
} 

// Generic 
public class Response<T> : Response 
{ 
    public T Value { get; set; } 
} 

我想有一個List<Response>,其中當我訪問這個對象我得到的Value屬性作爲對象。

但是,當我收到此對象作爲泛型,訪問T值屬性並隱藏對象的Value屬性。

我希望清楚,如果不是,請讓我知道。

編輯:這是一個測驗。因此,每個問題都有答案。例如在MultipleChoiceQuestion中,它可以具有幾個答案A,B,C,D作爲視圖形狀,或者可以是字符串或整數。

public abstract class Question 
{ 
    public Question(string questionText) 
    { 
     this.QuestionText = questionText; 
    } 

    public string QuestionText { get; set; } 
} 

// Non-generic 
public class Response 
{ 
    public object Value { get; } 
} 

// Generic 
public class Response<T> : Response 
{ 
    public T Value { get; set; } 
} 

public class MathProblemQuestion : Question 
{ 
    public Response Response { get; set; } 
} 

public class MultipleChoiseQuestion : Question 
{ 
    public Response Response { get; set; } 

    public IEnumerable<Response> PossibleResponses; 

    ... 
} 

public class TrueOrFalse : Question 
{ 
    ... 
} 
+0

你可以嘗試新的關鍵字,但我不知道它是否會在這種情況下工作。 public new T Value {get;組; } –

+3

3次閱讀,我沒有得到你想要的,你可以發佈一個僞代碼的例子,你試圖實現嗎? –

+0

我編輯了我的問題..對不起,英語不是我的母語(順便說一句,我也是墨西哥人,塔毛利帕斯州) –

回答

10

我個人只是給他們不同的名字。它將使你的生活簡單,大部分的代碼更清晰:

public abstract class Response 
{ 
    public abstract object ObjectValue { get; } 
} 

public class Response<T> : Response 
{ 
    public T Value { get; set; } 

    public override object ObjectValue { get { return Value; } } 
} 

請注意,我做了Response類抽象的 - 這是很難看到它如何能優雅否則工作;如果Response有其自己的存儲空間Value,那麼推測可能會將其設置爲非T值。希望使這個摘要不會成爲你的問題。

+0

也許你比我更瞭解主要目標。我的回覆中是否有錯誤? –

+0

他實際上可能需要使用非通用版本(例如動作與動作)。我認爲他的目標是編寫一個List ,其中編譯器知道每個實例的實際派生類型。 (這就是我根據我的回答...) –

+2

根據您的項目設計,如果您只在內部使用非通用基類'Response',則甚至可能在內部使'ObjectValue',因此API的消費者不會知道/不關心這樣一個事實,即你有一個物體升起,並且它不會在智能感知中暴露(滿足你「隱藏」財產的願望)。 –

2

我需要一個非通用類,因爲我打算插入這個類的對象,並在List<T>

不知道我的理解是插入。 A List<T>當然可以擁有泛型類型。

var ls = new List<List<int>>; // works! 

如果回落到使用object到處那有什麼用仿製藥的地步?您不再爲所有意圖和目的設置強類型集合,因爲基礎數據(您真正關心的數據)的類型爲object

但是,當我收到此對象作爲泛型,訪問T值屬性並隱藏對象的Value屬性。

如果使用Response<object>然後Tobject你的類型的所有實例。

也許我在這裏錯過了一些東西。如果我能爲你詳細說明嗎?我看不出爲什麼你的泛型類型不起作用。

編輯:我想我現在明白了。您希望單個List<T>擁有具有不同通用參數的對象Response。如果可能的話,我建議限制每個泛型類型來實現一個特定的接口,即,

public interface IResponseData 
{ 
    // whatever 
} 

public class Response<T> where T : IResponseData 
{ 
    public T Value { get; set; } 
} 

現在,如果你需要允許其不共享共同的祖先int S和其他類型的,那麼這將無法工作,喬恩斯基特有你更好的解決方案。

0

如果您做以下(使用「new」關鍵字),你會隱藏在基類中的屬性:

// Non-generic 
public class Foo 
{ 
    public object Value { get; set; } 
} 

// Generic 
public class Foo<T> : Foo 
{ 
    public new T Value { get; set; } 
} 

除非你加用不同的名稱另一個屬性我不明白的方式在那附近。我不完全理解爲什麼你需要有不同版本的課程才能使用列表,你可以有一個列表< Foo < T>>很好。

0

我假設你正在尋找在同一個列表中插入不同類型的響應,並使響應的對象版本不可設置。但是下面的代碼不起作用,因爲屬性自動生成的後備存儲不綁在一起:

// Non-generic 
public class Response 
{ 
    public object Value { get; private set; } 
} 
// Generic 
public class Response<T> : Response 
{ 
    public new T Value { get; set; } 
} 

public static void Main() 
{ 
    List<Response> List = new List<Response>() { new Response<int>() { Value = 1 }, new Response<string>() { Value = "p" } }; 

    // Throws NullReferenceException 
    Console.WriteLine(list[0].Value); 
    Console.WriteLine(list[1].Value); 
} 

試試這個,它使用一個受保護的領域來支持的屬性:

// Non-generic 
public class Response 
{ 
    protected object valueObject; 

    public object Value 
    { 
     get 
     { 
      return valueObject; 
     } 
    } 
} 
// Generic 
public class Response<T> : Response 
{ 
    public new T Value 
    { 
     get 
     { 
      return (T)valueObject; 
     } 
     set 
     { 
      valueObject = value; 
     } 
    } 
} 

public static void RunSnippet() 
{ 
    List<Response> list = new List<Response>() { new Response<int>() { Value = 1 }, new Response<string>() { Value = "p" } }; 

    Console.WriteLine(list[0].Value); 
    Console.WriteLine(list[1].Value); 
} 
0

如果我正確地理解了你的問題,只要你願意在你閱讀他們的時候手動列表你的列表元素,就可以做你想做的事情。

你的問題的第一部分是,你如何「隱藏」一種新的不同類型的繼承屬性,並且你已經實現了這一點。您不需要任何特殊關鍵字來替換屬性。鑑於你的樣品類型:

public class Response 
{ 
    public object Value 
    { 
     get; 
     set; 
    } 
} 

public class Response<T> : Response 
{ 
    public T Value 
    { 
     get; 
     set; 
    } 

} 

你已經可以做到以下幾點:

// typeof(response.Value) == System.Object 
var response = new Response(); 

// typeof(responseint.Value) == System.Int32 
var responseint = new Response<int>(); 

但是,你正在進一步要求做,把它們放入一個List<Response>,仍然把他們當作自己的派生型,沒有明確的類型轉換就無法工作。 List<>的元素類型在編譯時是固定的,就編譯器而言,列表中的所有元素都具有該類型。如果需要,可以將更多的派生類型添加到列表中,但是一旦它們在那裏,那麼當退出時,編譯器只知道它們是基本類型。

在運行時,當然,實際的類型元數據是存在的,所以運行時知道如何把一個ResponseResponse<int>只要那它到底是什麼。爲了演示代碼,給出的ResponseResponse<int>上面的實例:

// this part is fine, but... 
var responses = new List<Response>(); 
responses.Add(response); 
responses.Add(responseint); 

// This will not work. 
responses[1].Value += 1; 

// But this will. 
(responses[1] as Response<int>).Value += 1; 
1

爲了做到你想要什麼,你需要兩個值聯繫在一起:

public abstract class Response 
{ 
    public object Value { get; set; } 
} 

public class Response<T> : Response 
{ 
    private T _value; 
    public new T Value 
    { 
     get { return _value; } 
     set { base.Value = _value = value; } 
    } 
} 

然而,正如其他人指出 - 你的前提是不正確的:你可以使用泛型類型作爲其他通用類型的類型參數:

List<Response<YourObject>> 

wou ld是完全有效的。