tags:

views:

45

answers:

4
public class Address
{
    public string streetno;
    public string streetname;
    public string suburb;
    public string postcode;
    public Country country;
}
public class Country
{
    public string name;
}

public class Person<A>
    where A : new()
{
    public A address;

    public Person()
    {
        address.country = new Country();
    }
}

when i compile the above code i get the following error: error CS1061: 'A' does not contain a definition for 'country' and no extension method 'country' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?)

any ideas on how I can over come this issue?

+7  A: 

Well, first you need to understand the error. What would you expect to happen if we wrote:

Person<string> x = new Person<string>();

That would create an object with an address field of type string. Now string doesn't have a country property, so it doesn't make sense.

It's not clear to me why you want it to be generic to start with, but you could add an extra constraint so that A has to be Address or a derived class (roughly speaking):

public class Person<A> where A : Address, new()

Now you'll just get a NullReferenceException - because you're not creating a new instance of the address... your constructor would need to change to:

public Person()
{
    address = new A();
    address.country = new Country();
}

Alternatively, for more flexibility you might want to create an IAddress interface and express the constraint in terms of that, instead of the class... but that's up to you. It's hard to recommend a concrete course of action without more details of what you're doing.

Jon Skeet
A: 

You cannot refer to specific properties of a generic type like that unless you've given a generic type constraint that has those properties. For example, if you declared your class like:

public class Person<T> where T : Address, new()
{
    public T address;

    public Person()
    {
        this.address.Country = new Country();
    }
}

of course that might defeat the purpose if you only have that address class. It seems odd that this is a generic class where your generic type parameter is an address. Another approach would be to use the dynamic keyword:

public class Person
{
    public dynamic address;

    public Person()
    {
        this.address.Country = new Country();
    }
}
Steve Michelotti
A: 

You have to restrict your type to one that supports the country property. Since using the Address class directly is rather pointless consider using some type of base class /interface.

public interface IAddress
{
    public string streetno { get; set; }
    public string streetname { get; set; }
    public string suburb { get; set; }
    public string postcode { get; set; }
    public Country country { get; set; }
}

public class Person<A>
    where A : IAddress
{
    public A address;

    public Person()
    {
        address.country = new Country();
    }
}
BrokenGlass
A: 

I probably submitted as a bad example

This is closer to what i have

namespace SomeNamespace { public class SomeHeader {

}

public class SomeParamaters
{

}

public class SomeRequest
{
    public SomeHeader Header;
    public SomeParamaters Parameters;
}

}

using SomeNamespace;

namespace MyNamespace {

public class Worker<A> 
    where A : new()
{
    public A req;

    public void DoSomeMeaningfulWork()
    {
        req.Header = new SomeHeader();
        req.Parameters = new SomeParamaters();
    }
}

} please note teh classes SomeXXX inherit from object and implement System.ComponentModel.INotifyPropertyChanged

the reason i chose generics was there are many request,header,paramters,respons,data,error groups. basically each type of reuest defines a family of these.

the worker classes - after having written 3 are exactly the same bar the request,header,paramters,respons,data,error.

I was unaware of the dynamic keyword - but it does sound like what i am after as i know exactly the properties that are needed to be called - they are exactly the same and of teh same type.

however my problem is i am using .net 3.5 and vs 2008

i have considered interfaces, and constraints but they just dont seem to work the current problem i am facing

Serhat
I don't see where an interface would not satisfy your requirements, given the code in DoSomeMeaningfulWork. Just put the common properties in that interface.
BrokenGlass