2009-10-09 7 views
2

J'ai une classe générique:constructeurs ambigus/contradictoires dans la classe générique

public class BaseFieldValue<T> 
{ 
    public BaseFieldValue() 
    { 
     //... 
    } 

    public BaseFieldValue(string value) 
    { 
     //... 
    } 

    public BaseFieldValue(T value) 
    { 
     //... 
    } 
} 

fin. Sauf ...

var myValue = new BaseFieldValue<string>("hello"); 

Oups. Le constructeur indésirable est appelé. Il y a plusieurs façons de régler le problème. Quelle est la meilleure solution?

+0

Peut-être vous pouvez essayer ceci: var maValeur = new BaseFieldValue ("bonjour" comme objet); – Amit

Répondre

7

je ne serais probablement faire l'une des surcharges dans une méthode de fabrication:

public static BaseFieldValue<T> Parse(string value){} 
+0

Que faire si BaseFieldValue est une classe de connexion de base de données et la chaîne est la chaîne de connexion? –

+1

@Yuriy cela serait encore viable dans ce cas. –

+0

@Rex, oui, mais cela fonctionnerait contrairement à d'autres classes de connexion à la base de données, en essayant simplement de préserver les motifs. –

2

Vous pouvez effectuer les opérations suivantes:

public class BaseFieldValue<T> 
{ 
    public struct Special 
    { 
     internal string m_value; 
     public Special(string value) 
     { 
      m_value = value; 
     } 
    } 

    public BaseFieldValue() 
    { 
     //... 
    } 

    public BaseFieldValue(Special value) 
    { 
     //... 
    } 

    public BaseFieldValue(T value) 
    { 
     //... 
    } 
} 

... ou, vous pouvez ajouter un paramètre supplémentaire ignoré booléen à votre constructeur spécial, juste pour le désamorcer.

+1

+1 pour votre dernière option – recursive

0

Un hack méchant, mais probablement pas pire que l'une des alternatives:

public class BaseFieldValue<T> 
{ 
    public BaseFieldValue() 
    { 
     // ... 
    } 

    public BaseFieldValue(StringWrapper value) 
    { 
     // ... 
    } 

    public BaseFieldValue(T value) 
    { 
     // ... 
    } 

    public class StringWrapper 
    { 
     private string _value; 

     public static implicit operator string(StringWrapper sw) 
     { 
      return sw._value; 
     } 

     public static implicit operator StringWrapper(string s) 
     { 
      return new StringWrapper { _value = s }; 
     } 
    } 
} 

Et maintenant, il peut être utilisé comme vous avez besoin:

// call the generic constructor 
var myValue = new BaseFieldValue<string>("hello"); 

// call the string constructor 
var myValue = new BaseFieldValue<int>("hello"); 
1

ne pouvaient pas faire de type Contraints faire ce Je voulais, donc ma solution de contournement est de supprimer le constructeur ambigu tout en conservant le cas particulier pour la chaîne:

public class BaseFieldValue<T> 
{ 
    public BaseFieldValue() 
    { 
     //... 
    } 

    public BaseFieldValue(T value) 
    { 
     //however many things you need to test for here 
     if (typeof(T) == typeof(string)) 
     { 
      SpecialBaseFieldValue(value.ToString()); 
     } 
     else 
     { 
      //everything else 
     } 
     //... 
    } 

    private void SpecialBaseFieldValue(string value) 
    { 
     //... 
    } 

} 
+0

Mais 'typeof (T)' sera * jamais * égal à 'typeof (chaîne)' lorsque vous utilisez une instance de 'BaseFieldValue ', 'BaseFieldValue ', 'BaseFieldValue ' etc. – LukeH

+0

Mon test d'unité pour string et int a bien fonctionné. –

0

Peut être que vous pouvez fami:

var myValue = new BaseFieldValue<Object>("hello" as Object); 
+0

@Amy cela semblerait aller à l'encontre du but d'avoir une classe générique. –

Questions connexes