Checking a nullable property after a null-conditional check of parent object - nullable

Appreciate there have been some question close to what I am asking but not quite like here. I have been checking the ?. operator and I came upon the following scenario. Situation is as follows:
internal class Dog
{
public int? Age { get; set; }
}
Checks in main code were as follows:
Dog d2 = new Dog() { Age = 10 };
int age1 = d2.Age.Value; // compiles okay
int age2 = d2?.Age.Value; // CS0266
I would like to know why the code line with age3 is requesting an explicit cast. d2.Age being type int? and Age.Value being type int doesn't vary between the two usages.

Once you use the null-condicional operator, the resulting value can be null. that's why it can never be int.
What you need is:
int age2 = (d2?.Age).Value;

Related

Prevent class properties to be null when instantiating a Dart class

Assuming I have this Dart class:
class Stock {
int id;
String externalCode;
String internalCode;
String name;
double quantity;
}
When I create a new instance of this object like Stock item = new Stock(); all the properties are null.
I know this is a Dart specific behavior, but when sending such objects to an API, since most backend languages like C#, Java etc. don't have nullable primitives exceptions occur when parsing to a corresponding model class.
What is the simplest approach to prevent int, double and bool properties of being null (set them to 0, 0.0 and false respectively) when instantiating a Dart class?
Since many classes might have a lot of properties, a hardwired instantiation like Stock item = new Stock(id: 0, quantity: 0 /*...and so on... */); it's out of the question.
Many thanks!
If you want a default value for members in a class you can just assign each member to a value in the class definition:
class Stock {
int id = 0;
String externalCode = "";
String internalCode = "";
String name = "";
double quantity = 0.0;
}
Alternative, you can also give default values to optional parameters like:
class Stock {
int id;
String externalCode;
String internalCode;
String name;
double quantity;
Stock(
{this.id = 0,
this.externalCode = '',
this.internalCode = '',
this.name = '',
this.quantity = 0.0});
}

How to set value inside nested forEach() in java8?

I have a case in which I am iterating the List<DiscountClass> and need to compare the list value with another List<TypeCode>, based on satisfying the condition (when Discount.code equals TypeCode.code) I need to set Discount.setCodeDescr(). How to achieve this with nested forEach loop in java 8? (I am not able to set after comparing the values in java 8 forEach).
for (Discount dis : discountList) {
for (TypeCode code : typeCodeList) {
if (dis.getCode().equals(code.getCode())) {
dis.setCodeDesc(code.getCodeDesc());
}
}
}
A possible solution using java 8 lambdas could look like this:
discountList.forEach(dis -> {
typeCodeList
.stream()
.filter(code -> dis.getCode().equals(code.getCode()))
.findAny()
.ifPresent(code -> dis.setCodeDesc(code.getCodeDesc()));
});
For each discount you filter the TypeCodes according to the code and if you find any you set the desc poperty to the one of the found TypeCode.
The other answer showed how to convert a nested loop to a nested functional loop.
But instead of iterating over a list of TypeCode, it's better to use a HashMap to get random access, or an enum like this:
public enum TypeCode {
CODE_1("description of code 1"),
CODE_2("description of code 2");
private String desc;
TypeCode(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
public class Discount {
private String typeCode; //assuming you can't have the type as TypeCode
private String desc;
public Discount(String typeCode) {
this.typeCode = typeCode;
}
//getters/setters
}
Then your code will change to:
Discount d1 = new Discount("CODE_1");
Discount d2 = new Discount("CODE_2");
List<Discount> discounts = List.of(d1, d2);
discounts.forEach(discount ->
discount.setDesc(TypeCode.valueOf(discount.getTypeCode()).getDesc()));

Writing to mutable property for a struct record is not allowed in F#. Why?

When I have the following code:
[<Struct>]
type Person = { mutable FirstName:string ; LastName : string}
let john = { FirstName = "John"; LastName = "Connor"}
john.FirstName <- "Sarah";
The compiler complains that "A value must be mutable in order to mutate the contents". However when I remove the Struct attribute it works fine. Why is that so ?
This protects you from a gotcha that used to plague the C# world a few years back: structs are passed by value.
Note that the red squiggly (if you're in IDE) appears not under FirstName, but under john. The compiler complains not about changing the value of john.FirstName, but about changing the value of john itself.
With non-structs, there is an important distinction between the reference and the referenced object:
Both the reference and the object itself can be mutable. So that you can either mutate the reference (i.e. make it point to a different object), or you can mutate the object (i.e. change the contents of its fields).
With structs, however, this distinction does not exist, because there is no reference:
This means that when you mutate john.FirstName, you also mutate john itself. They are one and the same.
Therefore, in order to perform this mutation, you need to declare john itself as mutable too:
[<Struct>]
type Person = { mutable FirstName:string ; LastName : string}
let mutable john = { FirstName = "John"; LastName = "Connor"}
john.FirstName <- "Sarah" // <-- works fine now
For further illustration, try this in C#:
struct Person
{
public string FirstName;
public string LastName;
}
class SomeClass
{
public Person Person { get; } = new Person { FirstName = "John", LastName = "Smith" };
}
class Program
{
static void Main( string[] args )
{
var c = new SomeClass();
c.Person.FirstName = "Jack";
}
}
The IDE will helpfully underline c.Person and tell you that you "Cannot modify the return value of 'SomeClass.Person' because it is not a variable".
Why is that? Every time you write c.Person, that is translated into calling the property getter, which is just like another method that returns you a Person. But because Person is passed by value, that returned Person is going to be a different Person every time. The getter cannot return you references to the same object, because there can be no references to a struct. And therefore, any changes you make to this returned value will not be reflected in the original Person that lives inside SomeClass.
Before this helpful compiler error existed, a lot of people would do this:
c.Person.FirstName = "Jack"; // Why the F doesn't it change? Must be compiler bug!
I clearly remember answering this question almost daily. Those were the days! :-)

Dart: How to bind to variables annotated with int via Web UI?

What is the best practice in Dart when dealing with classes as data records?
To Elaborate: When writing an app, it is likely that a class for a table row will be created. As in
class Item { int itemid, String itemName, double score }
Item item = new Item();
This allows compile time catching of any typos etc. in Dart. (Unlike using a class that relies on NoSuchMethod.)
It will also need a corresponding string structure to bind to the HTML such as
<input id="itemname" type="text" bind-value="itemEdit.itemName">
So the Dart would be:
class ItemEdit { String itemId, String itemName, String score }
ItemEdit itemEdit = new ItemEdit();
Next we need a way to get from one to the other, so we add a method to Item
fromStrings(ItemEdit ie) {
itemid = ie.itemId == null ? null : int.parse(ie.itemId);
itemName = ie.ItemName;
score = ie.score == null ? null : double.parse(ie.score);
}
And the other way around:
toStrings(ItemEdit ie) {
ie.itemid = itemId == null ? '' : ie.itemId.toString();
ie. itemName = itemName == null ? '' : itemname; // Web_ui objects to nulls
ie.score = score == null ? null : score.toStringAsFixed(2);
}
Also, we get jason data from a database, so we need to add another method to Item:
fromJson(final String j) {
Map v = JSON.parse(j);
itemid = v['itemid'];
itemname = v['itemname'];
score = v['score'];
}
And we need to be able to revert to default values:
setDefaults() { itemId = 0; itemName = "New item"; score = 0; }
This verbosity gets me feeling like I am writing COBOL again!
There is something fundamental missing here - either in my understanding, or in the Dart/WebUI libraries.
What I would like to write is something like
class Item extends DataRecord {
int itemid = 0,
String itemName = 'New item',
double score = 0.0;
}
Then, without further coding, to be able to write code such as
item.toStrings();
...
item.fromStrings();
...
item.fromJson(json);
...
item.setDefaults(); // results in {0,'New item',0.0}
And to be able to write in the HTML:
value="{{item.strings.score}}"
If this was possible, it would be quicker, simpler, clearer, and less error prone than the code I am writing at the moment.
(Full disclosure, this answer is written with the assumption that at least one bug will be fixed. See below)
Three suggestions that might help.
Use named constructors to parse and create objects.
Take advantage of toJson() when encoding to JSON.
Use bind-value-as-number from Web UI
1) Named constructors
import 'dart:json' as json;
class Item {
int itemid;
String itemName;
double score;
Item.fromJson(String json) {
Map data = json.parse(json);
itemid = data['itemid'];
itemName = data['itemName'];
score = data['score'];
}
}
2) Encoding to JSON
The dart:json library has a stringify function to turn an object into a JSON string. If the algorithm encounters an object that is not a string, null, number, boolean, or collection of those, it will call toJson() on that object and expect something that is JSON-encodable.
class Item {
int itemid;
String itemName;
double score;
Map toJson() {
return {'itemid':itemid, 'itemName':itemName, 'score':score};
}
}
3) Now, having said that, sounds like you want to easily bind to HTML fields and get primitive values back, not just strings. Try this:
<input type="number" min="1" bind-value-as-number="myInt" />
(Note, there seems to be a bug with this functionality. See https://github.com/dart-lang/web-ui/issues/317)
(from https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/8JEAA5OxJOc)
Just found a way to perhaps help a little in the this situation:
class obj {
int gapX;
String get gapXStr => gapX.toString();
set gapXStr(String s) => gapX = int.Parse(s);
...
Now, from the HTML you can use, for example
bind-value="gapXStr"
and in code you can use
x += ob.gapX;

Using NoRM to access MongoDB from F#

Testing out NoRM https://github.com/atheken/NoRM from F# and trying to find a nice way to use it. Here is the basic C#:
class products
{
public ObjectId _id { get; set; }
public string name { get; set; }
}
using (var c = Mongo.Create("mongodb://127.0.0.1:27017/test"))
{
var col = c.GetCollection<products>();
var res = col.Find();
Console.WriteLine(res.Count().ToString());
}
This works OK but here is how I access it from F#:
type products() =
inherit System.Object()
let mutable id = new ObjectId()
let mutable _name = ""
member x._id with get() = id and set(v) = id <- v
member x.name with get() = _name and set(v) = _name <- v
Is there an easier way to create a class or type to pass to a generic method?
Here is how it is called:
use db = Mongo.Create("mongodb://127.0.0.1:27017/test")
let col = db.GetCollection<products>()
let count = col.Find() |> Seq.length
printfn "%d" count
Have you tried a record type?
type products = {
mutable _id : ObjectId
mutable name : string
}
I don't know if it works, but records are often good when you just need a class that is basically 'a set of fields'.
Just out of curiosity, you can try adding a parameter-less constructor to a record. This is definitely a hack - in fact, it is using a bug in the F# compiler - but it may work:
type Products =
{ mutable _id : ObjectId
mutable name : string }
// Horrible hack: Add member that looks like constructor
member x.``.ctor``() = ()
The member declaration adds a member with a special .NET name that is used for constructors, so .NET thinks it is a constructor. I'd be very careful about using this, but it may work in your scenario, because the member appears as a constructor via Reflection.
If this is the only way to get succinct type declaration that works with libraries like MongoDB, then it will hopefuly motivate the F# team to solve the problem in the future version of the language (e.g. I could easily imagine some special attribute that would force F# compiler to add parameterless constructor).
Here is a pretty light way to define a class close to your C# definition: it has a default constructor but uses public fields instead of getters and setters which might be a problem (I don't know).
type products =
val mutable _id: ObjectId
val mutable name: string
new() = {_id = ObjectId() ; name = ""}
or, if you can use default values for your fields (in this case, all null):
type products() =
[<DefaultValue>] val mutable _id: ObjectId
[<DefaultValue>] val mutable name: string

Resources