2

This is kind of hard to explain, so bear with me.

In PHP, if you wanted create a new property in a class, you could without doing anything. The following code would work perfectly.

    class testClass
{
    public function __construct()
    {
    }
}

$test = new testClass;
$test->propone = "abc";
echo $test->propone;

I would like to do the same thing, only in C# and with a struct. Is this possible?

Yes, I know, this sounds really clunky. I am trying to simulate a sort of associative array, where there is none. In my environment (NET Microframeworks), hashtables and dictionaries are not supported (yet).

Thanks!

jeb
  • 78,592
  • 17
  • 171
  • 225
chris12892
  • 1,634
  • 2
  • 18
  • 36

3 Answers3

4

Don't simulate an associative array - go write one and use it.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
3

As far as I know there's no way to add properties dynamically at runtime. Nor is there a way to add properties at compile-time aside from adding them directly to the declaration. In my opinion, this is good as it maintains the type-safety expected from C#.

However, couldn't you make a primitive hashtable using List<KeyValuePair<int, List<KeyValuePair<string, object>>>> and String.GetHashCode()? Something like the following (untested and part-pseudocode, but you get the idea):

class HashTable<T>
{
    private List<KeyValuePair<int, List<KeyValuePair<string, T>>>> _table = 
        new List<KeyValuePair<int, List<KeyValuePair<string, T>>>>();

    private void Set(string key, T value)
    {
        var hashcode = key.GetHashCode();
        List<KeyValuePair<string, T>> l;
        if(!_table.TryGetValue(hashcode, out l))
        {
            l = new List<KeyValuePair<string, T>>();
            _table.Add(hashcode, l);
        }

        T o;
        if(l.TryGetValue(key, out o))
        {
            if (o != value)
                l.Single(x => x.Key == key).Value = o;
        }
        else
            l.Add(new KeyValuePair(key, value));
    }

    private T Get(string key)
    {
        List<KeyValuePair<string, T>> l;
        object o;
        if(!(_table.TryGetValue(hashcode, out l) && 
            !l.TryGetValue(key, out o)))
        {
            throw new ArgumentOutOfRangeException("key");
        }

        return o;
    }
}

The following should help you with TryGetValue:

public bool TryGetValue<TKey, TValue>(this List<KeyValuePair<TKey, TValue>> list, 
    TKey key, out TValue value)
{
    var query = list.Where(x => x.Key == key);        
    value = query.SingleOrDefault().Value;
    return query.Any();
}
lc.
  • 113,939
  • 20
  • 158
  • 187
  • Thanks. The trouble is that I am pretty new to CSharp, so I'm sure that is only amplifying my difficulties. I know exactly what I want, just not how to do it. The code you posted looks great, I just have no idea how to implement it in non-psudo code. – chris12892 Jun 05 '10 at 04:09
  • 1
    @chris12892 I think it's actually pretty non-pseudo-code as is; the only thing you might have to work out how to do is a `TryGetKey` on `List>`. Might I suggest looking into `IEnumerable.SingleOrDefault`? – lc. Jun 05 '10 at 04:18
  • I've edited this to show you what I mean...hope it helps. I've also made the `HashTable` class a generic as well, so you don't always have to use `object` (among a couple other things for readability). – lc. Jun 05 '10 at 04:31
  • Sure. Depending on how many keys you have, it may be better to either remove the hashing altogether and just make an associative `List>` (for a small number of keys), or implement something better than O(n) for searching hashes, like a binary tree (for large number of keys). – lc. Jun 05 '10 at 04:45
  • The list is going to have between 10-15 entries, so optimization isn't much of an an issue. – chris12892 Jun 05 '10 at 04:54
1

In C# version 4.0, as released with .NET 4.0 and Visual Studio 2010, the new pseudo type dynamic can allow you to do what you want - though if you're new to C# (as you seem to be) it's likely the techniques involved will be a bit deep.

All you need to do is to implement the appropriate interface; once this is done, any client code that uses your object dynamically may access on-the-fly properties (and methods) much like your PHP example.

References if you want to know more ...

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Bevan
  • 43,618
  • 10
  • 81
  • 133