2011-04-16 63 views
1

我正在寻找一种方法来对待所有.Net数据类型一致,所以我可以创建下面的模式,其中任何类型实施IGetValue<out T>将投掷到IGetValue<object>。出于某种原因,如果T是struct,它不起作用,我不明白为什么。有没有一种方法可以实现以下模式?我需要一个通用的类/接口任何.Net数据类型

public interface IGetValue<out T> 
{ 
    T Value 
    { 
     get; 
    } 
} 

public class GetValue<T> : IGetValue<T> 
{ 
    public GetValue(T value) 
    { 
     _value = value; 
    } 

    private T _value; 
    public T Value 
    { 
     get { return _value; } 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     IGetValue<string> GetString = new GetValue<string>("Hello"); 
     IGetValue<int> GetInt = new GetValue<int>(21); 

     //This works!!! 
     if (GetString is IGetValue<object>) 
     { 
      Console.WriteLine("GetValue<string> is an IGetValue<object>"); 
     } 
     else 
     { 
      Console.WriteLine("GetValue<string> is not an IGetValue<object>"); 
     } 

     //This doesn't work!!! Why???? 
     if (GetInt is IGetValue<object>) 
     { 
      Console.WriteLine("GetValue<int> is an IGetValue<object>"); 
     } 
     else 
     { 
      Console.WriteLine("GetValue<int> is not an IGetValue<object>"); 
     } 

     Console.ReadKey(); 
    } 
} 

编辑:

我意识到发生了什么,我想在这里完成,似乎含糊其辞,但是这是一个更大的设计,其解释是太冗长的一部分。我需要的是让我的所有IGetValue<T>与一个名为“Value”的属性共享一个通用类型或接口,并返回一个object。为什么是冗长的部分。

+0

对象的价值是非常基本的概念。你想在这里完成什么? – 2011-04-16 10:41:48

回答

0

我最终通过创建非泛型IGetValue接口并在类中明确实现它来解决我的直接需求。这里的解决方案:

public interface IGetValue 
{ 
    object Value 
    { 
     get; 
    } 
} 

public interface IGetValue<out T> 
{ 
    T Value 
    { 
     get; 
    } 
} 

public class GetValue<T> : IGetValue<T>, IGetValue 
{ 
    public GetValue(T value) 
    { 
     _value = value; 
    } 

    private T _value; 
    public T Value 
    { 
     get { return _value; } 
    } 

    object IGetValue.Value 
    { 
     get { return _value; } 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     IGetValue<string> GetString = new GetValue<string>("Hello"); 
     IGetValue<int> GetInt = new GetValue<int>(21); 

     if (GetString is IGetValue) 
     { 
      Console.WriteLine("GetValue<string> is an IGetValue"); 
     } 
     else 
     { 
      Console.WriteLine("GetValue<string> is not an IGetValue"); 
     } 


     if (GetInt is IGetValue) 
     { 
      Console.WriteLine("GetValue<int> is an IGetValue"); 
     } 
     else 
     { 
      Console.WriteLine("GetValue<int> is not an IGetValue"); 
     } 

     Console.ReadKey(); 
    } 
} 
8

它不起作用,因为通用方差不适用于值类型...他们有不同的表示,而与参考类型的方差可能发生,而CLR不必执行任何转换。

因此,例如,您可以将IEnumerable<string>视为IEnumerable<object>,但不能将IEnumerable<int>视为IEnumerable<object>

+0

好的,谢谢你的解释,但是有没有办法实现上面的模式。 – Verax 2011-04-16 10:22:30

+1

@Verax:不是书面的,没有。 'Foo '永远不会是'Foo '。尽管如此,很难确切地告诉你想要做什么。 – 2011-04-16 10:52:44

+0

对于模糊性,我很抱歉。这是更大设计的一部分(正如您可能已经意识到的那样),我将不得不解释更大的设计,让任何人都能完全理解我的目标。但是这对于这个论坛来说太冗长了。请回答我这个问题。 'int'继承自'object'(最终),是吗? 'object'是一个引用类型,是吗?那么为什么'int'需要被装箱成为一个引用类型,如果它首先从引用类型继承? – Verax 2011-04-16 11:23:21

相关问题