Reputation: 1
UPDATE: This does not work the way I was hoping it would so, as others have stated below, this is not really a valid approach. Will be handling what I need another way.
I've created an interface with a method using a generic parameter, and a class that implements it. But in the class implementation, I get an error that the class doesn't implement a member that is on the class. Which seems odd.
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;
}
}
This gives "Error CS1061 'ClassA' does not contain a definition for 'name' and no accessible extension method 'name' accepting a first argument of type 'ClassA' could be found (are you missing a using directive or an assembly reference?)"
I'm sure I've got something wrong here but I'm not sure what it is.
Upvotes: 0
Views: 852
Reputation: 112279
If in a given class you always want to call the method with the same parameter type, the solution is to add the generic type parameter to the interface instead:
interface InterfaceA<T>
{
String MethodA(T obj);
}
Then you can implement it like this
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;
}
}
Upvotes: 0
Reputation: 118937
The problem is likely caused by you re-using the ClassA
name for the generic type. In this case, that is hiding the real definition of ClassA
. So, use another name for it, it's common to use T
in C#. Now it could be any type, but if you want to make sure it has the name
property, then you need a generic type constraint. For example, this would work:
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;
}
}
Of course, there's now a weird relationship between ClassA
and InterfaceA
so you may want to extract the name
property out as it's own interface too. For example:
public interface INamed
{
string name { get; }
}
Now your other code would look like this:
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;
}
}
Upvotes: 4
Reputation: 7111
Ignore the fact that you know that ClassA
has a name
property.
The compiler sees that MethodA
is a member of InterfaceA
(an interface that ClassA implements). That method is generic in type T
, where T
has no constraints. You are implementing MethodA
with ClassA
as the type parameter. You could have used any type. When you call the aClass.name
getter, the compiler says "Hey, there are no contraints on T, you don't get to use any of its members".
To fix this, add an interface like:
public interface IHaveAName
{
string name {get;}
}
and then change your interface definition to:
interface InterfaceA
{
String MethodA<T>(T obj) where T: IHaveAName;
}
Then declare that ClassA implements both interfaces:
public class ClassA : InterfaceA, IHaveAName
You may want to rethink what you are doing (my guess is that the reason you are doing this would be more apparently if this wasn't a dummied up example with meaningless names). It's hard to fathom why you have things structured this way given the information you have presented.
Upvotes: 2