C
C#3mo ago
Jason_Bjorn

✅ A nicer way to create an on-demand property?

Is there a nicer way to create sum here?
Foo f = new() {
X = 3,
Y = 4
};

f.Dump();

class Foo
{
public required int X { get; init; }
public required int Y { get; init; }
private int? sum = null;

public int Sum
{
get
{
Console.WriteLine("Calculating Sum");
sum ??= X + Y;
return sum.Value;
}
}
}
Foo f = new() {
X = 3,
Y = 4
};

f.Dump();

class Foo
{
public required int X { get; init; }
public required int Y { get; init; }
private int? sum = null;

public int Sum
{
get
{
Console.WriteLine("Calculating Sum");
sum ??= X + Y;
return sum.Value;
}
}
}
7 Replies
Jason_Bjorn
Jason_BjornOP3mo ago
I was thinking about using Lazy but that doesn't seem to clean thing up
Foo f = new()
{
X = 3,
Y = 4
};

f.Dump();

class Foo
{
public required int X { get; init; }
public required int Y { get; init; }
private int? sum = null;

public int Sum
{
get
{
Console.WriteLine("Calculating Sum");
sum ??= X + Y;
return sum.Value;
}
}

private Lazy<int> bum; // no longer needs to be int? which is nice
public int Bum // getter no longer needs to worry about the logic behind the value of bum, which is nice
{
get
{
return bum.Value;
}
}

public Foo() // constructor needed to let Bum know how to get the value of bum
{
bum = new Lazy<int>(() =>
{
Console.WriteLine("Calculating Bum");
return X + Y;
});
}
}
Foo f = new()
{
X = 3,
Y = 4
};

f.Dump();

class Foo
{
public required int X { get; init; }
public required int Y { get; init; }
private int? sum = null;

public int Sum
{
get
{
Console.WriteLine("Calculating Sum");
sum ??= X + Y;
return sum.Value;
}
}

private Lazy<int> bum; // no longer needs to be int? which is nice
public int Bum // getter no longer needs to worry about the logic behind the value of bum, which is nice
{
get
{
return bum.Value;
}
}

public Foo() // constructor needed to let Bum know how to get the value of bum
{
bum = new Lazy<int>(() =>
{
Console.WriteLine("Calculating Bum");
return X + Y;
});
}
}
Is the bum approach better?
SleepWellPupper
SleepWellPupper3mo ago
You're trying to implement lazy behavior. So using Lazy seems generally like a good approach. Do you require thread safety? Do you not care about the extra allocation? Then Lazy will probably fit the bill. Nothing wrong with doing it manually either if your specific usecase doesn't suffer for it. There's no "better" approach to be recommended without more detail on your specific usecase imo In fact, in your specific sample code, I'd go for a manual implementation since the null check and factory are cheap plus the factory is side effect free and so concurrent execution is a non-issue.
Jason_Bjorn
Jason_BjornOP3mo ago
putting the logic of initializing bum into the constructor just seems weird
SleepWellPupper
SleepWellPupper3mo ago
so use a field initializer private readonly Lazy<int> _lazySum = new(()=>X+Y); Or extract the factory delegate into a method.
Jason_Bjorn
Jason_BjornOP3mo ago
field initializers cannot reference non-static properties
// method 3 using Lazy<int> and field initilizer
private Lazy<int> tum = new Lazy<int>(() =>
{
Console.WriteLine("Calculating tum");
return X + Y;
});
public int Tum
{
get
{
return tum.Value;
}
}
// method 3 using Lazy<int> and field initilizer
private Lazy<int> tum = new Lazy<int>(() =>
{
Console.WriteLine("Calculating tum");
return X + Y;
});
public int Tum
{
get
{
return tum.Value;
}
}
SleepWellPupper
SleepWellPupper3mo ago
right. Constructor it is, then :)
Jason_Bjorn
Jason_BjornOP3mo ago
Thanks
Want results from more Discord servers?
Add your server