With only a bit of twitches you can get a much more flexible design:
publicclassReadValueOnlyXTimesThingy<T>{privateT_value;publicR1V(intmaxNumberOfReads,Tvalue){if(maxNumberOfReads<=0)thrownewArgumentOutOfRangeException("maxNumberOfReads must be a positive value");ReadsLeft=maxNumberOfReads;_value=value;}publicintReadsLeft{get;privateset;}publicTValue{get{if(ReadsLeft<=0){_value=default(T);}ReadsLeft--;return_value;}}}
And the usage:
varselfDestructingMessage=newReadValueOnlyXTimesThingy<string>(3,"this message will self destruct after 3 reads.");// some code herevartheMessage=selfDestructingMessage.Value;
Notes:
This allows as many reads as set in it's constructor.
In case T is a value type, it's 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 get false back. One way to handle this is to restrict the T to reference types only, another is to change the property return type to a tuple of bool, 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.
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
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.
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
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)".
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
Welcome tag moderator AKA Unofficial DEV cheerleader. While most of my friends are found on SnapChat or Tic-Toc, you can find me here. And I OOP, but I’m not a VSCO girl.
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
The first WriteLine gives "Hello, Class" but the second one throw an error, namely {"Object reference not set to an instance of an object."} when evaluating var _returning = _value; so one must have atry{}finally{} in the property declaration.
LATER
In fact, even
try{return_value;}finally{_value=null;}
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 second r1vc.Value returns null. So getting klasse of null is an error. Soooooo ... I need to do something like
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.
varchannel=Channel.CreateBounded<int>(1);
I love that the designers made the decision to have a separate ChannelReader<T> and ChannelWriter<T>. You can simply pass channel.Reader to your consumer and channel.Writer to your producer (if you desire that separation). This will give you what you want. You can call channel.Reader.TryRead. If it succeeds, it will be removed from the channel. Otherwise, it just informs you there was no value to take.
if(channel.Reader.TryRead(outvarvalue)){// Use the value.}
Channels can be further customized by way of BoundedChannelOptions. For instance, you can specify BoundedChannelFullMode, which determines the desired outcome if you attempt to write to the channel when it's already full.
Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.
Location
Perth, WA Australia
Education
A few diplomas.
Work
Software Engineer at [Daisy Digital](https://daisydigital.com.au/)
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.