In the beginning, there was code:
public abstract class A
{
private string _someValue;
public string SomeValue
{
get
{
if (_someValue == null)
_someValue = GetValue();
return _someValue;
}
}
protected virtual string GetValue() { /* logic */ }
}
public class B : A
{
protected override string GetValue()
{
return base.GetValue() + GetMoreValue();
}
private string GetMoreValue() { /* logic */ }
}
And the code said, "Let there be bugs!" and there were bugs.
Seriously now.
I have an instance of B, and when I get SomeValue, I get the same SomeValue of A, without the MoreValue.
The even weirder part came when I put a breakpoint on SomeValue's Get method:
It turns out that _someValue gets its value before the Get method is ever called.
Something is very wrong here.
UPDATE:
Thanks for the comments! Shortened code, and added forgotten return type in B method.
It turns out I was making a stupid mistake.
(I would delete the question, but I figured others can learn from my blooper.)
I had a watch on SomeValue.
The result? Get SomeValue was called the moment I started debugging.
(Which is a little weird, because I had a breakpoint on the Get method which didn't activate. For some reason, watches don't trigger breakpoints.)
*(As for the wrong value, that had nothing to do with inheritance -
GetMoreValue simply happened to return an empty string.)
Related
My setter code is not running here, I think by design because I am setting the same reference.
Is there syntax I can use to ensure the setter runs?
var settings = new Settings();
var a = settings.ReferenceVariable;
a.Value1++;
settings.ReferenceVariable = a; // Setter is not running here, so changes to 'a' are not persisted in database
// One workaround is to set to a different value, then set back to my value. This isn't a good solution for me
settings.ReferenceVariable = null; // Setter does run
settings.ReferenceVaraible = a; // Setter does run
public class Settings
{
public MyClass ReferenceVariable
{
get => GetSettingValueFromDatabase();
set => SetSettingValueToDatabase(value);
}
}
Edit: Thanks everyone for your help, I found the issue, I'm using Fody/PropertyChanged package, which does modify property setters, and checks for changes. Their changes aren't visible to me while debugging, so it was confusing to track down
When you say "the setter is not running" - are you saying the set => SetSettingValueToDatabase(value) line is never reached, or are you infering this only by the fact that the expected side effects from SetSettingValueToDatabase are not observed?
Because my gut feeling would be that the setter and the function SetSettingValueToDatabase itself are actually called, but MyClass has an internal optimization to skip the actual database operation if the value "hasn't changed", implemented like so:
private MyClass _cachedValue;
private bool _isLoaded = false;
private MyClass GetSettingValueFromDatabase() {
if (!_isLoaded) {
_cachedValue = DoActuallyLoadFromDatabase()
_isLoaded = true;
}
return _cachedValue;
}
private void SetSettingValueToDatabase(MyClass newValue) {
if (!_isLoaded || _cachedValue != newValue) {
DoActuallySaveToDatabase(newValue);
_cachedValue = newValue;
_isLoaded = true;
}
}
The != would then most likely fall back to object.ReferenceEquals, which would yield true since the reference of newValue and _cachedValue still match - hence no DB write or cache update, hence it looks as if the setter wasn't called, when actually just its side effect weren't triggered.
You can verify this by changing the property getter/setter to
get {
var res = GetSettingValueFromDatabase();
Debug.WriteLine($"get will return {res}");
return res;
}
set {
Debug.WriteLine($"set called with {value}");
SetSettingValueToDatabase(value);
}
My suspicion is that the debug output will be
get will return MyNamespace.MyClass
set called with MyNamespace.MyClass
set called with null
set called with MyNamespace.MyClass
rather than
get will return MyNamespace.MyClass
set called with null
set called with MyNamespace.MyClass
indicating the setter was indeed called as expected.
On a side note: a setter that triggers a database write operation is not a good design. Setters should be usually designed to be light-weight operations, not triggering a potentially locking hefty database operation. Rather use a method, that should potentially even be asynchronous.
Not clear what exactly you're doing here, but I think your comments are telling:
settings.ReferenceVariable = a; // Setter is not running here, so changes to 'a' are not persisted in database
but then you have:
settings.ReferenceVaraible = a; // Setter does run
Obviously the lines of code are exactly the same here, so my guess would be that you're expecting to link a to your Database, such that a would be a kind of a handle/portal to your database and you can modify a and get those changes telegraphed into your database.
This isn't going to work. The setter only runs when you set the value of settings, not when you set the value of a. It might be that you are updating a after the fact, but updating a doesn't force the call to SetSettingValueToDatabase.
How you handle this depends on how you want to restructure your code. I would wait to write a until you're done doing whatever operations you need to do with a, but you could also add a kind of a listener mechanic to a.
I have no idea what's in a, but you could do something like the following. This is a bit more code than I meant to write lol, but I'll put some closing comments after the code block.
public interface IChanged
{
void Subscribe(System.EventHandler subscriber);
void Unsubscribe(System.EventHandler subscriber);
}
public class MyClass : IChanged
{
private System.EventHandler subscribers;
private int myInt;
public int MyInt
{
get => myInt;
set
{
myInt = value;
subscribers?.Invoke(this, null);
}
}
private string myString;
public string MyString
{
get => myString;
set
{
myString = value;
subscribers?.Invoke(this, null);
}
}
public void Subscribe(System.EventHandler subscriber)
{
subscribers += subscriber;
}
public void Unsubscribe(System.EventHandler subscriber)
{
subscribers -= subscriber;
}
}
public class Settings
{
private MyClass myClass;
public MyClass ReferenceVariable
{
get => GetSettingValueFromDatabase();
set
{
if (myClass != null)
{
if (myClass != value)
{
myClass.Unsubscribe(OnReferenceVariableChanged);
}
}
myClass = value;
SetSettingValueToDatabase(value);
value.Subscribe(OnReferenceVariableChanged);
}
}
private void OnReferenceVariableChanged(object sender, System.EventArgs e)
{
SetSettingValueToDatabase(ReferenceVariable);
}
private MyClass GetSettingValueFromDatabase()
{
// You would get this from a Database
return new MyClass();
}
private void SetSettingValueToDatabase(MyClass myClass)
{
// do stuff
}
}
Here there's an IChanged interface that sets up a mechanism to subscribe to changes. You don't need any information here, you just need a heads up that a changed. You can slap the IChanged interface on whatever you want and use it for a variety of classes.
The trick then is to add the subscribers?.Invoke(this, null); line to each property in MyClass. If you don't use properties then you don't have a way to add this line and thus you won't get notifications if/when the fields are changed.
Then, in Settings, you keep track of a private MyClass myClass to know when you're getting a new instance of MyClass, so you can unsubscribe from the old one. Fire off your SetSettings methods, and then Settings adds itself as a subscriber to the MyClass's property changes.
Now, anytime a property changes, the MyClass class alerts all its subscribers, and the Settings subscriber in particular can use that as a trigger to re/write the settings to the database.
There's nothing special there in the Settings getter, so you might want to consider unsubscribing myClass there, setting it to whatever you pulled from the database, and hooking up the subscriber to that new instance, but I don't know anything about your code so I don't want to push that as "the" answer.
I'm working with some C# code that's using .Net 4 Lazy loads and I'm not super familiar with it. I'm trying to figure out if this particular code is useless or not.
Originally the property and code below where in the same class, but now I've moved the code to an external class that no longer has access to the private "lazyRecords" property. I'm wondering what the point of checking "lazyRecords.IsValueCreated" is since the lazyRecords.Value has not been invoked yet, wouldn't it always be false? Or is it checking to see if another thread somehow invoked the Value? Or is it doing this in case of a thread exception that resulted in not loading the object?
Property:
private Lazy<List<Record>> lazyRecords;
public List<Record> Records
{
get
{
return lazyRecords.Value;
}
set
{
lazyRecords = new Lazy<List<Record>>(() => value);
}
}
Code:
public Category LoadCategory(BaseClient client)
{
Category category = new Category();
category.Records = client.RecordClient.GetRecordsByCategoryID(category.ID);
if (lazyRecords.IsValueCreated)
{
category.WorldRecord = category.Records.FirstOrDefault();
}
else
{
category.WorldRecord = client.RecordClient.GetWorldRecord(category.ID);
}
}
The code is pretty useless, yes. To help you understand why, consider this very minimal version of Lazy (the real class has more options and logic to take care of multiple threads, but this is the rough idea):
public class Lazy<T>
{
private readonly Func<T> _creator;
private T _cachedValue;
public Lazy(Func<T> creator) => _creator = creator;
public bool IsValueCreated { get; private set; }
public T Value
{
get
{
if (!IsValueCreated)
{
_cachedValue = _creator();
IsValueCreated = true;
}
return _cachedValue;
}
}
}
The delegate passed to the constructor is called on demand, the first time the Value is requested. In the code you've posted there is no point to this because the delegate simply returns the value passed into the setter.
As to the LoadCategory method, the code you posted is hard to decipher. It directly accesses lazyRecords, implying it's a method of the same class. But then it accesses Records on a different object.
I have a struct like this (simplified for brevity):
public struct Period
{
public DateTime? Start { get; private set; }
public DateTime? End { get; private set; }
public bool IsMoment
{
get { return this.Start.HasValue && this.Start == this.End; }
}
public Period(DateTime? start, DateTime? end) : this()
{
this.Start = start;
this.End = end;
}
public override string ToString()
{
return this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End);
}
}
Everything works fine, but ReSharper is showing a warning on this.Start.Value.ToString:
Possible 'System.InvalidOperationException'
If I copy the body of the IsMoment property into the condition, the warning goes away, but I'd like to be able to reuse the property. I can disable the ReSharper warning with a comment (which is what I have done for the moment), or by changing ToString to string.Format, but I have a handful of other places like this in my code and it got me thinking. I'd try to resolve this using code contracts, but unfortunately I don't have a whole lot of experience with code contracts and I'm not sure how it would look.
Is there anyway I use code contracts to indicate to ReSharper that if IsMoment is true, then Start is not null?
Do something like this in IsMoment:
contract.ensures(result == false || start <> null);
(That's not exactly right. I'm typing this on my phone.)
UPDATE:
The problem could be due to the possibility of multithreaded code changing the value of Start between the IsMoment test and the Start.Value evaluation.
It may be more correct to copy the value into a local variable that cannot be modified by other threads.
public override string ToString()
{
Period local = this;
return local.IsMoment
? local.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", local.Start, local.End);
}
This looks like some unnecessary work, and it may look inefficient, but it more "correct". If your struct is small, though, this may actually be more efficient in many cases.
Have tried wrapping parens around it?
public override string ToString()
{
return (this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End));
}
This might be a case for using Contract.Assume.
public override string ToString()
{
if (this.IsMoment) {
Contract.Assume(this.Start.HasValue);
return this.Start.Value.ToString("g");
}
else
return string.Format("{0:g} – {1:g}", this.Start, this.End));
}
I have class named "config" that have private string variable named "param".
I need to get from "config" class "param" variable sometimes as int type sometimes as bool type or string.
As I understand I need create 3 properties in config class,each property have to convert type, as follow:
The first property converts string to int, the second converts string to bool, the third property gets me the string value.
The class should look something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
But I don't know how can those properties be used in accordance to the variable type that I want to get out of class.
This code won't compile - int and such are reserved keywords and cannot be used as identifiers. You can either try naming your properties something like Int32Value, StringValue, etc., or try this:
public static implicit operator bool (Config config)
{
return bool.Parse(config.param);
}
public static implicit operator int (Config config)
{
return int.Parse(config.param);
}
This will allow for much cleaner code:
Config c = GetConfig("foo");
var isFeatureEnabled = false || c;
var spacing = 23 + GetConfig("bar");
You forgot to give your properties names. How would you expect to reference them? Something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
Note that I also fixed the casing in your calls to .Parse(). C# is case-sensitive. I also replaced the call to bool.TryParse() with bool.Parse(). The former (when used correctly, which this wasn't because it was missing a parameter) will only tell you if it is a bool, it won't tell you what value the bool actually has. (For example, bool.TryParse('false' out someBool) will return true.)
Of course, this code is a bit dangerous. You'll want to start with some more defensive programming to check those values. Basically, look up TryParse() and how to use it correctly. Something like this, for example:
public int ParamAsInt
{
get
{
var tmp = default(int);
if (int.TryParse(param, out tmp))
return tmp;
else
// do something else? throw a specific exception?
}
}
Additionally, what is the purpose of this code? It seems like a very rushed and poor design. For any given value of param (how is that even being set, by the way?) this just sort of randomly tries to expose typed properties for it. If you guess the correct one, you're still left with others that will throw exceptions. Surely there's a much cleaner way to accomplish what you're trying to do. So what are you trying to do?
I found the following syntax as a VB.NET property and I'm trying to convert it to c#, but I'm not sure how to accomplish that.
Public Property SomeText(ByVal someEnumThing as SomeEnum) As String
Get
Select Case someEnumThing
//figure out what string to return
End Select
End Get
Set(ByVal Value as String)
Select Case someEnumThing
//figure out what string to set
End Select
End Set
End Property
I've never seen a property done like this before, any ideas?
I guess you're referring to the arguments for the property. Well, as far as I know, C# only supports them for indexers, which cannot have a name (e.g. this[SomeEnum someEnumThing] {}).
If you want to get a similar behavior, you can create a helper class with an indexer property and use it to expose the "name" of the property:
public class YourClass {
public struct SomeTextProperty {
private readonly YourClass owner;
internal SomeTextProperty(YourClass owner) {
this.owner = owner;
}
public string this[SomeEnum someEnumThing] {
get {
return owner.GetSomeText(someEnumThing);
}
set {
owner.SetSomeText(someEnumThing, value);
}
}
}
public SomeTextProperty SomeText {
get {
return new SomeTextProperty(this);
}
}
private string GetSomeText(SomeEnum someEnumThing) {
// implementation to get it
}
private void SetSomeText(SomeEnum someEnumThing, string value) {
// implementation to set it
}
}
Hmm... maybe the switch statement?
It is impossible to create a Property in C# which has arguments, unless it's the default property:
public double this[int index]
{
get {...}
set {...}
}
Just one of those areas where VB differs from C#.
It is not recommended to use syntax like this since you will not be able to use that property from a C# project that references this assembly.
If you're talking about the fact that the property is parameterized...
There's no direct translation for this in c# that I know of. Basically this is carryover from VB6 where you could make this weird quasi-collection property for a class. The easiest way to get similar functionality is to create a dictionary object and either publicly expose it or create an accessor. Where the VB code accesses this property like Class.SomeText("SomeKey") your C# code will become Class.SomeDictionaryProperty["SomeKey"]
Unfortunately this still isn't quite the same since the collection accessor won't be able to "see" the index value. This has been a minor source of frustration for me as well in the past coming from a VB background.
The Select Case will be a switch statement. Is that what you are specifically referring to?
EDIT: here's what I was referring to in my comment to #Lucero's answer to get close to the VB.NET syntax.
private SomeEnum SomeEnumThing { get; set; }
public string SomeText {
get {
switch (SomeEnumThing) {
//figure out what string to return
}
}
set {
switch (SomeEnumThing) {
//figure out what string to set
}
}
}