更新:这不像我希望的那样工作,正如其他人在下面所说的那样,这不是一个真正有效的方法。将以另一种方式处理我需要的东西。
我创建了一个接口,其中包含一个使用泛型参数的方法和一个实现它的类。但是在类实现中,我收到一个错误,即该类没有实现该类上的成员。这看起来很奇怪。
interface InterfaceA
{
String MethodA<T>(T obj);
}
public class ClassA : InterfaceA
{
public String name { get; set; }
public ClassA()
{
this.name = "My Name";
}
public String MethodA<ClassA>(ClassA aClass)
{
String result = aClass.name; //ERROR IS ON THIS LINE
return result;
}
}
public class ClassB : InterfaceA
{
public String test1 { get; set; }
public ClassB()
{
this.test1 = String.Empty;
}
public String MethodA<ClassB>(ClassB obj)
{
String result = obj.test1;
return result;
}
}
public class ClassC : InterfaceA
{
public String test2 { get; set; }
public ClassC()
{
this.test2 = String.Empty;
}
public String MethodA<ClassC>(ClassC obj)
{
String result = obj.test2;
return result;
}
}
这给出了“错误 CS1061 'ClassA' 不包含 'name' 的定义,并且无法找到接受类型为 'ClassA' 的第一个参数的可访问扩展方法 'name'(您是否缺少 using 指令或程序集参考?)"
我确定这里有问题,但我不确定是什么。
答案 0 :(得分:4)
该问题很可能是由于您将 ClassA
名称重新用于泛型类型所致。在这种情况下,这隐藏了 ClassA
的真正定义。因此,为它使用另一个名称,在 C# 中使用 T
是很常见的。现在它可以是任何类型,但如果您想确保它具有 name
属性,那么您需要一个泛型类型约束。例如,这将起作用:
interface InterfaceA
{
string MethodA<T>(T obj) where T : ClassA;
//^^^^^^^^^^^^^^^^
}
public class ClassA : InterfaceA
{
public String name { get; set; }
public ClassA()
{
this.name = "My Name";
}
public string MethodA<T>(T aClass) where T : ClassA
//^^^^^^^^^^^^^^^^
{
String result = aClass.name;
return result;
}
}
当然,现在 ClassA
和 InterfaceA
之间存在一种奇怪的关系,因此您可能希望将 name
属性提取出来,因为它也是自己的接口。例如:
public interface INamed
{
string name { get; }
}
现在您的其他代码将如下所示:
interface InterfaceA
{
string MethodA<T>(T obj) where T : INamed;
//^^^^^^^^^^^^^^^^
}
public class ClassA : InterfaceA, INamed
{
public String name { get; set; }
public ClassA()
{
this.name = "My Name";
}
public string MethodA<T>(T aClass) where T : INamed
//^^^^^^^^^^^^^^^^
{
String result = aClass.name;
return result;
}
}
答案 1 :(得分:2)
忽略您知道 ClassA
具有 name
属性这一事实。
编译器看到 MethodA
是 InterfaceA
(ClassA 实现的接口)的成员。该方法在 T
类型中是通用的,其中 T
没有约束。您正在使用 MethodA
作为类型参数实现 ClassA
。您可以使用任何类型。当您调用 aClass.name
getter 时,编译器会说“嘿,T 没有限制,您不能使用它的任何成员”。
要解决此问题,请添加如下界面:
public interface IHaveAName
{
string name {get;}
}
然后将您的接口定义更改为:
interface InterfaceA
{
String MethodA<T>(T obj) where T: IHaveAName;
}
然后声明 ClassA 实现了两个接口:
public class ClassA : InterfaceA, IHaveAName
您可能想重新考虑您在做什么(我的猜测是,如果这不是一个带有无意义名称的虚拟示例,那么您这样做的原因会更明显)。鉴于您所提供的信息,很难理解为什么您要以这种方式组织事物。
答案 2 :(得分:0)
如果在给定的类中你总是想调用具有相同参数类型的方法, 解决方案是将泛型类型参数添加到接口中:
interface InterfaceA<T>
{
String MethodA(T obj);
}
那么你就可以这样实现了
public class ClassA : InterfaceA<ClassA>
{
public String name { get; set; }
public ClassA()
{
this.name = "My Name";
}
public String MethodA(ClassA aClass)
{
String result = aClass.name; //No more error here.
return result;
}
}