So I want a variable that I can assign a value to then, later on, read it but have the read be destructive, that is, once I've retrieved the value I want to be unable to read it again.
I wrote something to do that some years ago and I'm still using it but I'm not exactly happy with it and am trying to think of a better, more generic, implementation.
public class R1V
{
private int _count;
private readonly string _value;
public R1V(string value)
{
_count = 1;
_value = value;
}
public string Get()
{
switch (_count)
{
case 1:
_count = 0;
return _value;
default:
return null;
}
}
}
is what it is at the moment. It currently works only with strings. I want it to work with anything. Currently it doesn't forget the value it has stored, it just stops you getting access to it. That should change too.
In another object I have
LastMessage = new R1V(fullMsg);
and then elsewhere I can execute LastMessage.Get()
and know, if it's null, that there's nothing new from the object that exposes LastMessage.
Any ideas?
Top comments (15)
With only a bit of twitches you can get a much more flexible design:
And the usage:
Notes:
default
will return a value -0
for numbers,false
for bool and so on. This might not be a desirable outcome once the value have been read the allowed number of times, since it's default value might be indistinguishable from the previous value (think of initializing this class with 1, false - you'll always getfalse
back. One way to handle this is to restrict theT
to reference types only, another is to change the property return type to a tuple ofbool, T
- or perhaps throw an exception - Though that would probably be the last thing I would recommend - as this kind of thing is what Eric Lippert would call a vexing exception, and as usual, he knows what he is writing about.Extra love-button clicking for the use of the word "thingy".
Here's the source...
It might be cleaner to return a Maybe, insted of returning null or default(T).
If you are already using this nuget, then yes. Otherwise, assuming you're only working with reference types, It introduces more complexity than a simple
is object
test for reference types.Anyway, this is a good option to keep in mind.
Hey Bruce,
Here is my variant:
And then there's the property variant
I've created a dotnet core project and put that in it. Currently I'm getting a error in the
finally
clause: "A readonly field cannot be assigned to (except in a constructor or a variable initializer)".Riiiight. Needed some
public
s.Looks good except Type would have to be nullable.
A little late to the party, but here's my implementation using implicit conversion to and from the ReadLimit class.
Thanks to everyone who contributed.
As I was fiddling with this, I thought, "hey why not just"
Well, that's fine until you do this
after having defined the class
Klasse
asThe first WriteLine gives "Hello, Class" but the second one throw an error, namely
{"Object reference not set to an instance of an object."}
when evaluatingvar _returning = _value;
so one must have atry{}finally{}
in the property declaration.LATER
In fact, even
doesn't cut it in the
Klasse
version.LATER AGAIN
Actually, it does cut it. So perhaps the first one is okay too. The problem is in the second
Console.WriteLine(r1vc.Value.klasse);
because the secondr1vc.Value
returns null. So gettingklasse
of null is an error. Soooooo ... I need to do something likeImplemented this program in java.. That's why i didn't faced those issues except the return value null conversion error.
Glad you solved it. Cheers 🥂
I use
System.Threading.Channels
for this. Read this if you want a super detailed introduction to channels in general. For your specific problem, I simply make a bounded channel with a capacity of 1.I love that the designers made the decision to have a separate
ChannelReader<T>
andChannelWriter<T>
. You can simply passchannel.Reader
to your consumer andchannel.Writer
to your producer (if you desire that separation). This will give you what you want. You can callchannel.Reader.TryRead
. If it succeeds, it will be removed from the channel. Otherwise, it just informs you there was no value to take.Channels can be further customized by way of
BoundedChannelOptions
. For instance, you can specifyBoundedChannelFullMode
, which determines the desired outcome if you attempt to write to the channel when it's already full.I am receiving that as a late Christmas present. Thank you very much.