2010-09-11 6 views

Répondre

9

Ceci est essentiellement ce que la contrainte new() se résume à:

class Factory<T> where T : new() 
{ 
    public T Create() 
    { 
     return new T(); 
     //  ^^^^^^^ 
     //  this requires the new() type constraint. 
    } 
} 

Maintenant, vous n'êtes pas autorisé à transmettre des arguments au constructeur. Si vous voulez néanmoins initialiser l'objet nouvellement créé, vous pouvez réaliser ceci par exemple. en introduisant une contrainte supplémentaire:

interface ILikeBananas 
{ 
    double GreenBananaPreferenceFactor { get; set; } 
} 

class Factory<T> where T : ILikeBananas, new() 
{ 
    public T Create(double greenBananaPreferenceFactor) 
    { 
     ILikeBananas result = new T(); 
     result.GreenBananaPreferenceFactor = greenBananaPreferenceFactor; 

     return (T)result; 
     //  ^^^^^^^^^ 
     //  freely converting between ILikeBananas and T is permitted 
     //  only because of the interface constraint. 
    } 
} 

Notez qu'une autre façon d'instancier un objet est par Activator.CreateInstance, qui vous donne une plus grande liberté, comme le passage d'arguments directement à un constructeur.

Activator.CreateInstance ne nécessite pas strictement la contrainte new(); cependant, le type instancié doit toujours fournir un constructeur approprié.

+0

Bien que ce soit une bonne réponse, je déteste personnellement quand quelqu'un écrit un 'Factory ' avec une contrainte 'where T: new()' tout en disant que tous les objets '' T' doivent être instanciés en utilisant cette usine! " Comme, si vous voulez vraiment limiter l'instanciation à votre usine, ne * demandez * pas qu'elle soit instanciable en dehors de votre usine! –

+0

_ @ Dan Tao, hmm ... Vous avez certainement un point là. Notez cependant que je n'ai * pas * dit * n'importe où dans ma réponse que 'Factory ' devrait être le créateur * exclusif * d'éléments de type 'T'. C'était simplement l'exemple le plus simple auquel je pouvais penser; peut-être le nom de type 'Usine ' suggère trop. – stakx

1

Il est rarement nécessaire dans le sens d'être le seul moyen d'accomplir quelque chose. Mais parfois, c'est la façon la plus facile de faire quelque chose. Par exemple, disons que vous écrivez un pool d'objets. Par exemple, par exemple. Quand quelqu'un veut prendre un objet du pool, il retourne un objet existant ou en crée simplement un nouveau s'il n'y en a pas. Vous pouvez ajouter la contrainte where T : new() pour vous permettre d'écrire simplement return new T();.

La contrainte n'est pas requise ici, car vous pourriez avoir accompli la même chose en prenant un Func<T> dans le constructeur du pool et en l'utilisant. On peut dire que cette méthode est en fait meilleure, car elle est plus flexible. Mais encore une fois, new T() est juste agréable et facile.

0

Je vais simplement donner un exemple simple. J'ai créé une méthode:

public T GetFromXml<T>(string xml) 
    where T: class, new() 
{ 
    if (String.IsNullOrEmpty(xml)) 
    { 
     return new T(); 
    } 
    return xml.AsObjectFromXml<T>(); 
} 

Et l'utiliser comme ceci:

Phones = GetFromXml<List<PhoneData>>(source.Phones); 

Parce que je préfère des collections vides sur les valeurs nulles.

Questions connexes