tags:

views:

363

answers:

3

In a C# application I am working on I have a very long identifier as follows:-

foo.bar.bwah.blah.whatever.very.very.huge

Whenever I to reference this object it's an absolute nightmare, and unfortunately I do need to reference it a lot:-

var something = foo.bar.bwah.blah.whatever.very.very.huge.a;
var somethingElse = foo.bar.bwah.blah.whatever.very.very.huge.b;
foo.bar.bwah.blah.whatever.very.very.huge.c = 12;

etc. etc.

I want to update this code using a far smaller alias of some kind, the problem is however that I want to change the underlying reference, and have the alias update also without explicitly updating the alias.

Currently if I do the following:-

foo.bar.bwah.blah.whatever.very.very.huge.a = "hello";
string shorter = foo.bar.bwah.blah.whatever.very.very.huge.a;
foo.bar.bwah.blah.whatever.very.very.huge.a = "world";
Console.WriteLine(shorter);

It will output "hello". What I want to achieve is something like the following:-

foo.bar.bwah.blah.whatever.very.very.huge.a = "hello";
string** shorterPointer = &foo.bar.bwah.blah.whatever.very.very.huge.a;
foo.bar.bwah.blah.whatever.very.very.huge.a = "world";
Console.WriteLine(**shorter);

Which would output "world" as required.

I believe you can achieve something like this using unsafe code in C#, however I cannot do that, I have to use safe code only.

Does anybody have any ideas how I might achieve this?

Please Note: This question is not about strings being immutable, I know they are - in fact I assumed they are for the purposes of the question. It might perhaps be simpler if I used some other type... so when I assign "hello" to a then "world" to a, I am instantiating different objects on each occasion, hence my stored reference to a becomes invalid after re-assignment.

+5  A: 

One way out is to use one or a pair of lambdas.

For example:

Func<string> getter = () => blah_de_blah;
Action<string> setter = x => blah_de_blah = x;

Now, you can use getter and setter to read and write the long identifier.

However, since your dots are member accessors, the easiest way of going about it is to take a reference to the immediate parent, like so:

var myHuge = foo.bar.bwah.blah.whatever.very.very.huge;
// now access myHuge.a everywhere

This is good practice in any case, as a long dotted expression like this is a violation of the Law of Demeter, which inhibits the flexibility of the codebase - it requires too much information in too many places.

Barry Kelly
That is very nice Barry you absolute life-saver!
kronoz
The dots *are* member access symbols!!! But your technique will work regardless.
kronoz
If so, then all you need do is keep a reference to huge, and dereference to get the "a" member every time.
Barry Kelly
Barry, what if I then reassign bar? It won't hold then.
kronoz
That's an excellent point about the law of Demeter, thank you, will take a look at the architecture!
kronoz
If you reassign to bar, then you'll break it, yes. However, that will break the lambda approach too - at best, the lambda will capture the root of the expression (an implicit "this" if any, or "foo" otherwise). Reassigning foo's "bar" property will break the reference in the same way.
Barry Kelly
The lambda approach should work surely? Won't it effectively act as a macro in this instance?
kronoz
Sorry, kronoz - I was assuming that you wanted reference semantics like a pointer to the underlying string field would give you. Yes, it will act like a function, but importantly, not like a reference to a reference.
Barry Kelly
A: 

First thing. I would rethink your architecture. That seems way too complicated! :)

Anyways, let's get to business.

Strings are immutable in .NET and that's your problem. When you change the object's property, you are creating a new string on memory and pointing there with the object's property. However, this does not change your string variable (why should it?). The variable hasn't changed, so it keeps pointing to the previous string.

That's the problem, now to the solution. I'd suggest creating a reference to the object that contains the string, just one level above, like this: foo.bar.bwah.blah.whatever.very.very.huge.a = "hello"; Huge huge = foo.bar.bwah.blah.whatever.very.very.huge; huge.a = "foo!";

Hope it helps! :)

Rafa G. Argente
Firstly this isn't about strings, I used that example on the assumption strings are immutable so that I could make my point more clearly! That was perhaps not the best choice! :-)Yes, but what if I want to re-assign the 'huge' object? also if say bwah was re-assigned we'd be getting wrong also.
kronoz
Oh and I don't think it's an architecture problem! Though perhaps it could be better constructed; The actual code is only say 3-4 fields deep, only the names are rather long. I think it's very possible for this problem to come up in a well-formed architecture.
kronoz
I see kronoz, it's true. Now I see your point. However, I think it's not worth it to complicate the code too much just to write shorter names. But maybe it's just me! Anyways, the question is interesting, I will keep an eye on it and post again if I come up with something!
Rafa G. Argente
+1  A: 

I would use namespace alias.

using myAlias = foo.bar.bwah.blah.whatever.very.very

then inside your method you just had to type: myAlias.huge.a = "hello";

Sergio
Isn't the using statement simply for type aliasing?
kronoz
you can only define namespaces with using. As the problem presented was a long long line of code, i guess this would work ;)
Sergio