2010-09-29 5 views
0
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(); 
    } 
} 

quand je compilez le code ci-dessus je reçois l'erreur suivante: erreur CS1061: « A » ne contient pas de définition de « pays » et aucune méthode extension « pays » acceptation un premier argument de type 'A' pourrait être trouvé (manque-t-il une directive using ou une référence d'assembly?)Impossible de créer la propriété pour une classe générique

Avez-vous des idées pour surmonter ce problème?

Répondre

7

Eh bien, vous devez d'abord comprendre l'erreur. Que voulez-vous attendre à arriver si nous écrivions:

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

Ce serait créer un objet avec un champ address de type string. Maintenant, string n'a pas de propriété country, donc cela n'a pas de sens.

Il est pas clair pour moi pourquoi vous voulez qu'il soit générique pour commencer, mais vous pourrait ajouter une contrainte supplémentaire pour que A doit être Address ou une classe dérivée (grosso modo):

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

maintenant, vous aurez juste un NullReferenceException - parce que vous n'êtes pas créer une nouvelle instance de l'adresse ... votre constructeur devrait changer pour:

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

Sinon, pour mo re flexibilité que vous pourriez vouloir créer une IAddressinterface et d'exprimer la contrainte en termes de cela, au lieu de la classe ... mais c'est à vous de décider. Il est difficile de recommander un plan d'action concret sans plus de détails sur ce que vous faites.

0

Vous ne pouvez pas faire référence à des propriétés spécifiques d'un type générique de ce type à moins que vous ayez donné une contrainte de type générique qui a ces propriétés. Par exemple, si vous déclarez votre classe comme:

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

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

bien sûr qui pourrait annuler le but si vous avez seulement cette classe d'adresse. Il semble étrange que ce soit une classe générique où votre paramètre de type générique est une adresse. Une autre approche serait d'utiliser le mot-clé dynamique:

public class Person 
{ 
    public dynamic address; 

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

Vous devez restreindre votre type à celui qui prend en charge la propriété du pays. Puisque l'utilisation directe de la classe Address est plutôt inutile, pensez à utiliser un type de classe/interface de base.

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(); 
    } 
} 
0

J'ai probablement soumis un mauvais exemple. C'est plus proche de ce que j'ai:

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(); 
     } 
    } 
} 

S'il vous plaît noter les classes SomeXXX héritant de l'objet et mettre en œuvre System.ComponentModel.INotifyPropertyChanged.

La raison pour laquelle j'ai choisi les génériques est qu'il y a beaucoup de requêtes, d'en-têtes, de paramètres, de respons, de données, de groupes d'erreurs. Fondamentalement, chaque type de demande définit une famille de ceux-ci.

Les classes de travailleurs - après avoir écrit 3 sont exactement la même chose que la requête, l'en-tête, les paramètres, les réponses, les données, les erreurs.Je n'étais pas au courant du mot-clé dynamique - mais cela ressemble à ce que je suis après car je connais exactement les propriétés qui doivent être appelées - elles sont exactement les mêmes et du même type.

Cependant, mon problème est, j'utilise .net 3.5 et 2008 vs

J'ai examiné les interfaces et les contraintes, mais ils ont juste ne semblent travailler pour le problème actuel, je suis confronté.

+0

Je ne vois pas où une interface ne satisferait pas vos besoins, étant donné le code dans DoSomeMeaningfulWork. Mettez simplement les propriétés communes dans cette interface. – BrokenGlass

Questions connexes