2008-10-25 4 views
9

Je voudrais faire la même chose en C#. Est-il possible d'utiliser des propriétés en C# avec les paramètres de la même manière que j'ai fait avec le paramètre 'Key' dans cet exemple VB.NET?Utilisation des propriétés get set typiques en C# ... avec les paramètres

Private Shared m_Dictionary As IDictionary(Of String, Object) = New Dictionary(Of String, Object) 
Public Shared Property DictionaryElement(ByVal Key As String) As Object 
    Get 
     If m_Dictionary.ContainsKey(Key) Then 
      Return m_Dictionary(Key) 
     Else 
      Return [String].Empty 
     End If 
    End Get 
    Set(ByVal value As Object) 
     If m_Dictionary.ContainsKey(Key) Then 
      m_Dictionary(Key) = value 
     Else 
      m_Dictionary.Add(Key, value) 
     End If 

    End Set 
End Property 

Merci

Répondre

14

Y at-il de toute façon d'utiliser les propriétés en C# avec des paramètres

Non Vous ne pouvez fournir le par défaut propriété en C# avec un argument, de modéliser un indexé ccess (comme dans un dictionnaire):

public T this[string key] { 
    get { return m_Dictionary[key]; } 
    set { m_Dictionary[key] = value; } 
} 

Les autres propriétés ne peuvent pas avoir d'arguments. Utilisez une fonction à la place. En passant, il est recommandé de faire la même chose dans VB afin que les autres langages .NET (C# ...) puissent utiliser votre code. D'ailleurs, votre code est inutilement compliqué. Quatre choses:

  • Vous n'avez pas besoin d'échapper l'identificateur String. Utilisez le mot-clé directement.
  • Pourquoi ne pas utiliser ""? Utilisez TryGetValue, c'est plus rapide. Vous interrogez le dictionnaire deux fois.
  • Votre setter n'a pas besoin de tester si la valeur existe déjà.

Public Shared Property DictionaryElement(ByVal Key As String) As Object 
    Get 
     Dim ret As String 
     If m_Dictionary.TryGetValue(Key, ret) Then Return ret 
     Return "" ' Same as String.Empty! ' 
    End Get 
    Set(ByVal value As Object) 
     m_Dictionary(Key) = value 
    End Set 
End Property 
+1

Belle réponse man. Je ne sais pas pourquoi vous suggérez d'utiliser "" au lieu de String.Empty cependant, ... l'original me semble plus explicite. – Stimul8d

+4

@ Stimul8d: Je ne suis pas. Comment '' "" 'n'est pas explicite? La seule différence que je vois entre les deux (et que, à mon humble avis, un programmeur * devrait * voir) est que String.Empty est six fois plus long, donc cela prend six fois plus d'espace et prend six fois plus de temps pour lire cela rend le code six fois pire. À titre de comparaison, c'est comme si nous utilisions 'Int32.Zero' au lieu de' 0'. –

+1

licorne nez: Je viens d'utiliser le même argument la semaine dernière! –

0

Votre exemple de code me paraît une conception très étrange et un abus de ce que les propriétés sont destinés. Pourquoi ne pas simplement une méthode d'instance AddOrUpdateKey:

Public Sub AddOrUpdateKey(ByVal Key As String, ByVal Value as Object) 
    If m_Dictionary.ContainsKey(Key) Then 
     m_Dictionary(Key) = Value 
    Else 
     m_Dictionary.Add(Key, Value) 
    End If 
End Sub 

Votre propriété renvoie également String.Empty si la clé n'existe pas, mais prétend retourner un Object, ni String.

+0

Hi Sören, L'utilisation d'une méthode ne me permet pas d'utiliser le code de cette façon: Example.DictionaryElement ["OneKey"] = "Hello world"; Console.WriteLine (Example.DictionaryElement ["OneKey"]); Merci beaucoup – Javier

4

La "bonne" façon de le faire en C# est de créer une classe enfant spécifiquement pour accéder à la collection. Il doit soit contenir la collection elle-même, soit avoir des liens internes avec la classe parente.

3

Voici un exemple pour vous (avec des changements le long des lignes des suggestions de Grauenwolf):

using System; 
using System.Collections.Generic; 

public class Test 
{ 
    public FakeIndexedPropertyInCSharp DictionaryElement { get; set; } 

    public Test() 
    { 
     DictionaryElement = new FakeIndexedPropertyInCSharp(); 
    } 

    public class FakeIndexedPropertyInCSharp 
    { 
     private Dictionary<string, object> m_Dictionary = new Dictionary<string, object>(); 

     public object this[string index] 
     { 
      get 
      { 
       object result; 
       return m_Dictionary.TryGetValue(index, out result) ? result : null; 
      } 
      set 
      { 
       m_Dictionary[index] = value; 
      } 
     } 
    } 


} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test t = new Test(); 
     t.DictionaryElement["hello"] = "world"; 
     Console.WriteLine(t.DictionaryElement["hello"]); 
    } 
} 
0

Merci Konrad, Alan, Grauenwolf,

En conclusion, je ne peux pas utiliser les propriétés C# exactement de la même manière que dans VB.NET ...: _ (De toute façon, vos réponses m'ont été très utiles, et je vais probablement apporter ces idées à mon code C#

En plus des réponses à la question question des propriétés, il y a d'autres bons points.Par exemple,

  • Utilisez TryGetValue, il est plus rapide. Vous interrogez le dictionnaire deux fois.
  • Votre setter n'a pas besoin de tester si la valeur existe déjà.

Merci Sören aussi, en utilisant une méthode ne pas s'intègre bien dans mes objectifs initiaux, mais merci beaucoup.

4

Un plus polyvalent, plus sûr, et d'une solution réutilisable à votre problème pourrait être la mise en œuvre d'un générique, la classe de propriété « paramétrés », comme ceci:

// Generic, parameterized (indexed) "property" template 
    public class Property<T> 
    { 
     // The internal property value 
     private T PropVal = default(T); 

     // The indexed property get/set accessor 
     // (Property<T>[index] = newvalue; value = Property<T>[index];) 
     public T this[object key] 
     { 
      get { return PropVal; }  // Get the value 
      set { PropVal = value; } // Set the value 
     } 
    } 

Vous pouvez ensuite mettre en œuvre un certain nombre de propriétés au sein de votre public class afin que les clients puissent établis/obtenir les propriétés avec un index, descripteur, clé de sécurité, ou autre, comme celui-ci:

public class ParameterizedProperties 
    { 
     // Parameterized properties 
     private Property<int> m_IntProp = new Property<int>(); 
     private Property<string> m_StringProp = new Property<string>(); 

     // Parameterized int property accessor for client access 
     // (ex: ParameterizedProperties.PublicIntProp[index]) 
     public Property<int> PublicIntProp 
     { 
      get { return m_IntProp; } 
     } 

     // Parameterized string property accessor 
     // (ex: ParameterizedProperties.PublicStringProp[index]) 
     public Property<string> PublicStringProp 
     { 
      get { return m_StringProp; } 
     } 
    } 

Enfin, le code client aurait accès à des propriétés « paramétrés » de votre classe publique comme ceci:

 ParameterizedProperties parmProperties = new ParameterizedProperties(); 
     parmProperties.PublicIntProp[1] = 100; 
     parmProperties.PublicStringProp[1] = "whatever"; 
     int ival = parmProperties.PublicIntProp[1]; 
     string strVal = parmProperties.PublicStringProp[1]; 

Bien sûr, cela semble bizarre, mais ça fait vraiment l'affaire. En outre, du point de vue du code client, ce n'est pas du tout bizarre - c'est simple et intuitif et il agit comme de vraies propriétés. Il ne rompt pas les règles C# et n'est pas non plus incompatible avec les autres langages gérés .NET. Et du point de vue de l'implémenteur de classes, la création d'une classe de modèles de propriétés «paramétrables», génériques et réutilisables rend le codage des composants relativement facile, comme illustré ici. REMARQUE: vous pouvez toujours remplacer la classe de propriété générique pour fournir un traitement personnalisé, tel que la recherche indexée, l'accès aux propriétés contrôlé par la sécurité ou tout ce que vous voulez.

À la votre!

Mark Jones

+0

+1 Merci Mark, ça a l'air bien! Je vérifierai – Javier

Questions connexes