2013-07-11 39 views
25

比方说,我有这样的接口和具体实施接口与泛型参数VS接口与通用方法

public interface IMyInterface<T> 
{ 
    T My(); 
} 

public class MyConcrete : IMyInterface<string> 
{ 
    public string My() 
    { 
     return string.Empty; 
    } 
} 

所以我对strings创建MyConcrete实现,我可以有一个int更具体的实施。没关系。但是,让我们说,我想做同样的事情,但与一般的方法,所以我有

public interface IMyInterface2 
{ 
    T My<T>(); 
} 

public class MyConcrete2 : IMyInterface2 
{ 
    public string My<string>() 
    { 
     throw new NotImplementedException(); 
    } 
} 

所以我也有同样IMyInterface2,但它定义了的T My<T>()手段仿制行为。在我的具体类中,我想实现My行为,但是对于具体的数据类型 - string。但是C#不允许我这样做。

我的问题是为什么我不能这样做? 换句话说,如果我可以创建MyInterface<T>的具体实现MyClass : MyInterface<string>并停止在这一点的通用性,为什么我不能用通用方法做到这一点 - T My<T>()

+1

当继承类型时,你不能*减少*能力,你只能添加它们。 –

回答

29

你的泛型方法的实现必须是通用一样,所以它必须是:

public class MyConcrete2 : IMyInterface2 
{ 
    public T My<T>() 
    { 
     throw new NotImplementedException(); 
    } 
} 

为什么你不能做My<string>()这里?由于接口契约需要一种方法,因此可以使用任何类型参数T调用该方法,并且必须履行该合同。

为什么你不能在此停止通用因为它会导致情况类似如下:

类声明:

public interface IMyInterface2 
{ 
    T My<T>(t value); 
} 

public class MyClass21 : IMyInterface2 
{ 
    public string My<string>(string value) { return value; } 
} 

public class MyClass22 : IMyInterface2 
{ 
    public int My<int>(int value) { return value; } 
} 

用法:

var item1 = new MyClass21(); 
var item2 = new MyClass22(); 

// they both implement IMyInterface2, so we can put them into list 
var list = new List<IMyInterface2>(); 
list.Add(item1); 
list.Add(item2); 

// iterate the list and call My method 
foreach(IMyInterface2 item in list) 
{ 
    // item is IMyInterface2, so we have My<T>() method. Choose T to be int and call with value 2: 
    item.My<int>(2); 

    // how would it work with item1, which has My<string> implemented? 
} 
+1

它需要公众'T我()' –

+0

如果我可以创造具体的执行MyInterface的作为MyClass的:MyInterface的在这一点上,我为什么不能做到阻止这种通用与通用的方法 - T的我( )? –

+1

@JevgenijNekrasov检查我的更新。当我的“我的”执行失败时,我展示了一种情况。 – MarcinJuraszek

0

因为你的接口声明泛型方法T My<T>(),但你实现不实现具有该特定签名的功能。

达到你想要什么,你需要提供的T泛型参数的接口,那么你的第一个例子:

public interface IMyInterface2<T> 
{ 
     T My(); 
} 

public class MyConcrete2 : IMyInterface2<string> 
{ 
    public string My() 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

我知道如何实现我想要的,我想知道为什么我不能阻止通用性,因为我可以使用接口 –

2

当你写泛型方法的定义是为保持占位符。调用该方法时,实际类型会显示在图片中。所以你应该写

public T My<T>() 
{ 
    throw new NotImplementedException(); 
} 

当你调用这个方法时,你可以在那里使用字符串。

+0

我想停止共享性,因为我可以使用通用接口(例如, MyClass:MyInterface

0

您的解决方案不起作用有两个原因。

首先,接口是合同。当你实现IMyInterface2时,你保证你将实现一个名为My的函数,它接受一个泛型类型参数并返回该类型。 MyConcrete2不这样做。

其次,C#泛型不允许任何类型的参数专门化。 (我希望C#支持这一点。)这是C++模板中常见的事情,您的示例可以编译,但如果012xx的任何用法不能用string调用My,则将无法编译。