2012-06-29 158 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是完全有效的。