1

Currently I am doing something along the lines of:

public class UselessClass
{
    public string x;
    public int y;
}

I only ever use this class once in a function...

Dictionary<string, UselessClass> dict;

I'd like to be able to edit the values of the UselessClass, so I believe a Tuple isn't sufficient as they are read-only once created. I'd also like to have the named variables x and y to do things like:

dict["hello"].y++;

Can I do this without having to have this UselessClass sitting around the code when really it's only ever used once for a function? Some sort of anonymous class with named variables?

To add more details:

This is purely used in an algorithmic function where I want to adjoin a string with certain variables, namely another string x and an integer representing a distance

The best way I can think of adding properties to an already existing class like string is by using a dictionary.

Rather than doing:

Dictionary<string, string> names;
Dictionary<string, int> distances;

which seems like a waste of memory, I'd rather get both names and distances in the same structure.

But the structure itself is meaningless on its own, it's only used in the algorithm to perform a calculation.

muzzlator
  • 742
  • 4
  • 10
  • 2
    Why private nested class does not work? If you need such one-off class your function is likely already too big and asking to be refactored - and than nested class would be just right... – Alexei Levenkov Sep 03 '14 at 15:40
  • Is named variables important or is design time checking of variables important. You could use `dynamic` but it won't help you at design time (no intelisense, no compiler errors if you make a mistake) – Scott Chamberlain Sep 03 '14 at 15:40
  • Alexei, the scope feels unnatural to me. Feels like the nested class belongs in the function where I use it, not outside – muzzlator Sep 03 '14 at 15:43
  • 1
    If you need to refer to the type (which you do in the dictionary definition), you can’t really use an anonymous type. I don’t see why you would think that declaring a separate type for each purpose would be bad. It’s definitely the best solution for many reasons. – poke Sep 03 '14 at 15:43
  • More context would be helpful for a good answer - Is the dictionary consumed outside of the class that creates it? Are there really just two properties or is it just simplified? Do you really need to mutate the instances or could you create a _new_ instance with different values? – D Stanley Sep 03 '14 at 15:45
  • Hi DStanley, I'll put more details in the question now – muzzlator Sep 03 '14 at 15:46
  • possible duplicate of [Non-read only alternative to anonymous types](http://stackoverflow.com/questions/9043848/non-read-only-alternative-to-anonymous-types) – Mike Zboray Sep 03 '14 at 15:47
  • Thanks mike z, Eric Lippert gave the exact answer I wanted to see. The real reason why it's not possible.. people potentially using them for hash keys rather than values :( – muzzlator Sep 03 '14 at 15:55
  • @muzzlator are you mutating the other string or just the distance? – D Stanley Sep 03 '14 at 15:57
  • @DStanley Just the distance – muzzlator Sep 03 '14 at 15:57
  • @poke It's the equivalent of doing: int i=0; for (; i – muzzlator Sep 03 '14 at 16:11

3 Answers3

3

No - anonymous types are immutable. If you want a mutable type use a class (not a struct). Using dynamic and ExpandoObject would be one alternative but you lose design-time type safety.

If you give some more context as how they are used there may be other alternatives.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
1

One possibility is like you said using Tuple but since their elements cannot be changed you can do a little "hack" if you wanna call it is to declare an Tuple<int[],string[]> so when you add an item to the dictionary you instantiate the tuple but with only 1 element in each array which can be manipulated:

Dictionary<string,Tuple<int[],string[]>> test = new Dictionary<string, Tuple<int[],string[]>>();
//here i add a new dict entry and to the int[] i assign the value 5.
test.Add("test1", new Tuple<int[], string[]>(new int[1]{5}, new string[1]));
test["test1"].Item1[0]++;
test["test1"].Item1[0]++;
//here the int will be 7.

Although i would go with the UselessClass...

terrybozzio
  • 4,424
  • 1
  • 19
  • 25
1

To provide a similar solution as terrybozzio, albeit a less hackish one (using a single-element array isn’t exactly that nice), you could also use a wrapper that makes a type mutable:

class Mutable<T>
{
    public Mutable(T value)
    {
        Value = value;
    }
    public T Value { get; set; }
}

You could then even use this for anonymous types:

var x = new {
    Foo = "Bar",
    Baz = new Mutable<int>(2)
};

Console.WriteLine(x.Baz.Value); // 2
x.Baz.Value++;
Console.WriteLine(x.Baz.Value); // 3

But as I said in a comment above, you can’t really use an anonymous type if you need to reference the type in the dictionary declaration. You could use a tuple, but overall, you gain a lot more flexibility if you just introduce a custom type. For example if you decide that you need another value in there (for whatever reason), then you can simply add it without everything breaking. If you on the other hand use a tuple or something similar, you would have to update every single use of it.

poke
  • 369,085
  • 72
  • 557
  • 602