我有以下界面:
public interface ISapFunction
{
void Import<T>(T obj);
T Export<T>();
void Call(RfcRepository repo, RfcDestination dest);
}
然后我尝试按如下方式实现它:
public class SapMaterialFormatter : ISapFunction
{
private static SapMaterialFormatter _self;
private string _formatted;
private string _raw;
private SapMaterialFormatter()
{
}
public void Import<string>(string obj)
{
_raw = obj;
}
public string Export<string>()
{
return _formatted;
}
public void Call(RfcRepository repo, RfcDestination dest)
{
var bapi = repo.CreateFunction("FUNCTION");
bapi.SetValue("IF_INPUT", _raw);
bapi.Invoke(dest);
_formatted = bapi.GetString("EF_OUTPUT");
}
public static SapMaterialFormatter Factory()
{
return _self ?? new SapMaterialFormatter();
}
}
但编译器抱怨,生成语法错误:
实施有什么问题?
答案 0 :(得分:7)
它们是通用方法参数,因此在调用这些接口方法时需要提供它们。
例如:impl.Import<string>(...)
。
您的实现应该只定义整个T
通用参数:
public void Import<T>(T obj)
{
}
如果您想获得所需的效果,则需要定义泛型类型参数T
并删除其方法范围的对应项:
public interface ISapFunction<T>
{
void Import(T obj);
T Export();
void Call(RfcRepository repo, RfcDestination dest);
}
答案 1 :(得分:2)
实施是实施开放式通用方法Import<T>
和Export<T>
所必需的,而不是封闭的通用方法,例如Import<string>
和Export<string>
。
实现类不指定T,而是调用方法的调用站点。
示例:
var sapFunction = ...;
sapFunction.Import<string>(...);
如果您确实希望实现类指定类型,您可以在界面中声明它,如下所示:
public interface ISapFunction <T>
{
..
}
然后实施它:
public class SapMaterialFormatter : ISapFunction<string>
答案 2 :(得分:2)
您的界面声明了泛型方法,因此您的实现也必须是通用的:
public class SapMaterialFormatter : ISapFunction
{
// shortened for brevity
public void Import<T>(T obj)
{
_raw = obj;
}
public T Export<T>()
{
return _formatted;
}
public void Call(RfcRepository repo, RfcDestination dest)
{
}
}
如果要创建具有特定类型的派生类,您可能想要声明您的界面:
public interface ISapFunction<T> // declare generic parameter here
{
void Import(T obj); // but not here
T Export();
void Call(RfcRepository repo, RfcDestination dest);
}
然后宣布您的班级实施ISapFunction<string>
:
public class SapMaterialFormatter : ISapFunction<string>
{
// shortened for brevity
public void Import(string obj)
{
_raw = obj;
}
public string Export()
{
return _formatted;
}
public void Call(RfcRepository repo, RfcDestination dest)
{
}
}
答案 3 :(得分:0)
您可以选择两种不同的方法来实现接口中方法的通用参数:
解决方案1。
public interface ISapFunction
{
void Import<T>(T obj);
T Export<T>();
}
public class SapMaterialFormatter : ISapFunction
{
private static SapMaterialFormatter _self;
private string _formatted;
private string _raw;
public static SapMaterialFormatter Factory()
{
return _self ?? new SapMaterialFormatter();
}
public void Import<T>(T obj)
{
throw new NotImplementedException();
}
public T Export<T>()
{
throw new NotImplementedException();
}
}
它包括在接口和实现类中将方法定义为泛型,它可以像这样使用:
var sap = new SapMaterialFormatter();
sap.Export<string>();
解决方案2。
public interface ISapFunction<T>
{
void Import(T obj);
T Export();
}
public class SapMaterialFormatter : ISapFunction<string>
{
private static SapMaterialFormatter _self;
private string _formatted;
private string _raw;
public static SapMaterialFormatter Factory()
{
return _self ?? new SapMaterialFormatter();
}
public void Import(string obj)
{
throw new NotImplementedException();
}
public string Export()
{
throw new NotImplementedException();
}
}
其中包括将接口声明为接受泛型并在方法中使用它。
然后您可以将其用作:
var sap = new SapMaterialFormatter();
sap.Export();
注意:我已经删除了方法的内容以确保代码编译,您可以随意更改样本。
答案 4 :(得分:0)
正如大家已经向您解释过的那样,您必须使您的实现变得通用,您无法指定类型。
主要原因是,如果我做这样的事情:
interface ISomething
{
T Method<T>();
}
class SomethingWithString : ISomething
{
public string Method<string>()
{
return "Hello World !";
}
}
class SomethingWithInt : ISomething
{
public int Method<int>()
{
return 42;
}
}
根据您的说法,SomethingWithString
和SomethingWithInt
都会实施ISomething
。
所以我可以写:
IEnumerable<ISomething> enumerable = new ISomething[]
{
new SomethingWithString(),
new SomethingWithInt()
};
在这里:
IEnumerable<?> results = enumerable.Select(x => x.Method()); // We may have a problem here...
除了使用对象/动态类型,我们无法知道Method
返回的类型。
这就是为什么你必须改变你的实施,其他答案已经告诉你如何做到这一点。