使用C#中的典型get set属性…带参数
我想在C#中做同样的事情。 有没有在C#中使用参数的属性,就像我在这个VB.NET示例中使用参数’Key’一样?
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
谢谢
无论如何在C#中使用带参数的属性
不可以。您只能在C#中使用参数提供默认属性,以建模索引访问(如在字典中):
public T this[string key] { get { return m_Dictionary[key]; } set { m_Dictionary[key] = value; } }
其他属性不能有参数。 请改用function。 顺便说一句,它建议在VB中执行相同的操作,以便其他.NET语言(C#…)可以使用您的代码。
顺便说一句,您的代码不必要地复杂化。 四件事:
- 您不需要转义
String
标识符。 直接使用关键字。 - 为什么不用
""
? - 使用
TryGetValue
,它更快。 您查询字典两次。 - 您的setter不必测试该值是否已存在。
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
在C#中执行此操作的“正确”方法是专门创建子类以访问该集合。 它应该保存集合本身或者具有与父类的内部链接。
一个更通用,更安全,可重用的问题解决方案可能是实现一个通用的“参数化”属性类,如下所示:
// Generic, parameterized (indexed) "property" template public class Property { // The internal property value private T PropVal = default(T); // The indexed property get/set accessor // (Property [index] = newvalue; value = Property [index];) public T this[object key] { get { return PropVal; } // Get the value set { PropVal = value; } // Set the value } }
然后,您可以在公共类中实现任意数量的属性,以便客户端可以使用索引,描述符,安全密钥等设置/获取属性,如下所示:
public class ParameterizedProperties { // Parameterized properties private Property m_IntProp = new Property (); private Property m_StringProp = new Property (); // Parameterized int property accessor for client access // (ex: ParameterizedProperties.PublicIntProp[index]) public Property PublicIntProp { get { return m_IntProp; } } // Parameterized string property accessor // (ex: ParameterizedProperties.PublicStringProp[index]) public Property PublicStringProp { get { return m_StringProp; } } }
最后,客户端代码将访问您的公共类的“参数化”属性,如下所示:
ParameterizedProperties parmProperties = new ParameterizedProperties(); parmProperties.PublicIntProp[1] = 100; parmProperties.PublicStringProp[1] = "whatever"; int ival = parmProperties.PublicIntProp[1]; string strVal = parmProperties.PublicStringProp[1];
当然,这看起来很奇怪,但绝对可以解决问题。 此外,从客户端代码的角度来看,它并不奇怪 – 它简单直观,就像真正的属性一样。 它不会破坏任何C#规则,也不会与其他.NET托管语言不兼容。 从类实现者的角度来看,创建一个可重用的,通用的“参数化”属性模板类使组件编码变得相对轻松,如此处所示。
注意:您始终可以覆盖通用属性类以提供自定义处理,例如索引查找,安全性控制的属性访问或您想要的任何内容。
干杯!
马克琼斯
以下是您的示例(根据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 m_Dictionary = new Dictionary(); 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"]); } }
您的代码示例让我感到非常奇怪,并且滥用了什么属性。 为什么不只是一个实例方法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
如果密钥不存在,您的属性也会返回String.Empty
,但声明返回Object
,也不返回String
。
谢谢康拉德,艾伦,格劳恩沃尔夫,
总而言之,我不能完全按照与VB.NET中相同的方式使用C#属性…:_(无论如何,你的答案对我来说非常有用,我可能会把这些想法带到我的C#代码中。
除了属性问题的答案,还有其他好处。 例如,
- 使用TryGetValue,它更快。 您查询字典两次。
- 您的setter不必测试该值是否已存在。
谢谢Sören,使用一种方法并不符合我最初的目标,但非常感谢。