Why this c# code throws a null exception?
bool boolResult = SomeClass?.NullableProperty.ItsOkProperty ?? false;
IsnĀ“t elvis operator supposed to stop evaluation (short circuit) once the NullableProperty evaluates to null?
In my understanding the line of code above is a shortcut for:
bool boolResult
if(SomeClass != null)
if(SomeClass.NullableProperty != null)
boolResult = SomeClass.NullableProperty.ItsOkProperty;
else
boolResult = false;
else
boolResult = false;
Did I assume wrong?
EDIT: Now I understand why I get it wrong, The line of code actually translates to something similar to:
bool boolResult
if(SomeClass != null)
boolResult = SomeClass.NullableProperty.ItsOkProperty;
else
boolResult = false;
And throws because NullableProperty is null...
You need to chain, since the NRE is on the second reference:
bool boolResult = SomeClass?.NullableProperty?.ItsOkProperty ?? false;
Related
I know that this topic has been asked by many times and I search for all possible solutions but unfortunately nothing solves my problem.
Here's my test case:
#Test
public void whenFindAllBy_thenReturnListofViewPlanDetailDto() {
java.sql.Date startDate = new java.sql.Date(new Date().getTime());
java.sql.Date endDate = new java.sql.Date(new Date().getTime());
Plan planA = new Plan();
planA.setName("Plan A - 2018");
entityManager.persist(planA);
entityManager.flush();
Module moduleA = new Module();
moduleA.setName("CSS");
moduleA.setDescription("CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.");
entityManager.persist(moduleA);
Module moduleB = new Module();
moduleB.setName("HTML");
moduleB.setDescription("Hypertext Markup Language is the standard markup language for creating web pages and web applications.");
entityManager.persist(moduleB);
PlanDetail planDetailA = new PlanDetail();
planDetailA.setInstructor("Mozilla Firefox Foundation");
planDetailA.setStartDate(startDate);
planDetailA.setEndDate(endDate);
planDetailA.setModule(moduleA);
planDetailA.setPlan(planA);
entityManager.persist(planDetailA);
PlanDetail planDetailB = new PlanDetail();
planDetailB.setInstructor("W3 Schools");
planDetailB.setStartDate(startDate);
planDetailB.setEndDate(endDate);
planDetailB.setModule(moduleB);
planDetailB.setPlan(planA);
entityManager.persist(planDetailB);
entityManager.flush();
List<ViewPlanDetailDto> plandetails = new ArrayList<>();
plandetails.add(new ViewPlanDetailDto(planDetailA.getId(), planDetailA.getModule().getName(), planDetailA.getModule().getDescription(), planDetailA.getInstructor(), planDetailA.getStartDate(), planDetailA.getEndDate()));
plandetails.add(new ViewPlanDetailDto(planDetailB.getId(), planDetailB.getModule().getName(), planDetailB.getModule().getDescription(), planDetailB.getInstructor(), planDetailB.getStartDate(), planDetailB.getEndDate()));
assertEquals(planRepository.findAllBy(planA.getId()), plandetails);
}
Stacktrace:
java.lang.AssertionError: expected: java.util.ArrayList<[ViewPlanDetailDto(detailId=1, name=CSS, description=CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript., instructor=Mozilla Firefox Foundation, startDate=2018-07-06, endDate=2018-07-06), ViewPlanDetailDto(detailId=2, name=HTML, description=Hypertext Markup Language is the standard markup language for creating web pages and web applications., instructor=W3 Schools, startDate=2018-07-06, endDate=2018-07-06)]> but was: java.util.ArrayList<[ViewPlanDetailDto(detailId=1, name=CSS, description=CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript., instructor=Mozilla Firefox Foundation, startDate=2018-07-06, endDate=2018-07-06), ViewPlanDetailDto(detailId=2, name=HTML, description=Hypertext Markup Language is the standard markup language for creating web pages and web applications., instructor=W3 Schools, startDate=2018-07-06, endDate=2018-07-06)]>
What I try:
Override equals on PlanDetail, ViewPlanDetailDto, Plan
but it all failed.
Equals and Hashcode overrides:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof ViewPlanDetailDto))
return false;
ViewPlanDetailDto other = (ViewPlanDetailDto) obj;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (detailId == null) {
if (other.detailId != null)
return false;
} else if (!detailId.equals(other.detailId))
return false;
if (endDate == null) {
if (other.endDate != null)
return false;
} else if (!endDate.equals(other.endDate))
return false;
if (instructor == null) {
if (other.instructor != null)
return false;
} else if (!instructor.equals(other.instructor))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (startDate == null) {
if (other.startDate != null)
return false;
} else if (!startDate.equals(other.startDate))
return false;
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((detailId == null) ? 0 : detailId.hashCode());
result = prime * result + ((endDate == null) ? 0 : endDate.hashCode());
result = prime * result + ((instructor == null) ? 0 : instructor.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((startDate == null) ? 0 : startDate.hashCode());
return result;
}
When I try to assert it it always fails even though the output is identical.
Based on IntelliJ's comparison failure, it highlighted on the trailing space on the expected part which I don't get how it ended having a trailing space.
You probably override equals() incorrectly .
To understand and correct your issue, you should start by the base : unit testing your equals() method (and by the way think of overriding hashCode() to be consistent with the equals() contract).
Whatever, overriding equals() by specifying all instance fields of the class to do some assertions in an unit test is generally something that you can avoid and that you have to if it gives an undesirable behavior to equals().
equals() has a semantic defined in Object.equals() :
Indicates whether some other object is "equal to" this one.
You should stick to that.
Generally I use a unit testing matcher library such as Harmcrest or AssertJ to perform assertions on the object's field in a non intrusive while being simple and clear.
With AssertJ, your assertion could look like :
Assertions.assertThat(planRepository.findAllBy(planA.getId()))
// assert result size
.hasSize(2)
// extract a field to assert
.extracting(ViewPlanDetailDto::getPlanDetail)
// extract still finer fields to assert
.extracting(PlanDetail::getId, p -> p.getModule().getName(), p -> p.getModule().geDescription(), ... other fields to assert)
// declare values expected
.containsExactly(Tuple.tuple(planDetailA.getId(), "CSS", "CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.",
planDetailB.getId(), "HTML", "Hypertext Markup Language is the standard markup language for creating web pages and web applications.",
... other expected tuples ));
I have csv file like this:
1392249600;EUR;CHF;USD;JPY;GBP
1392163200;GBP;JPY;USD;CHF;EUR
1392076800;GBP;CHF;EUR;JPY;USD
1391990400;JPY;USD;EUR;CHF;GBP
1391904000;GBP;EUR;CHF;USD;JPY
1391731200;GBP;EUR;CHF;JPY;USD
1391644800;EUR;CHF;USD;JPY;GBP
1391558400;JPY;USD;EUR;CHF;GBP
There can be over 15 000 rows in that file. I am trying to write code that could do such thing:
1.Takes first row saves it as parent. Then takes next 3 days as that childs.
2.Counts how often and which combination off childs with that parent are inside this file.
3.It creates something like summary for that so I could read todays combination and script shows the only the most frequent child combinations for next 3 days.
I don't have mathematical thinking so I have big problems to find solution myself.
What I think first I need script that generates all posible combinations of these colums made of EUR,CHF,USD,JPY,GBP so there is posible 5*4*3*2*1 = 120 combinations. Because they cant repeat in single row.
It will be like this.
First parent will be combination from first row like this: EUR;CHF;USD;JPY;GBP
Then 3 childs would be
GBP;JPY;USD;CHF;EUR
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
It saves this combination off parent and child elements.
Then again it starts from begining of the file, but moves one row below(like iteration +1).
then next all childs would be
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
GBP;EUR;CHF;USD;JPY
And again it saves these combinations for counting and make some frequency results.
And this cycle repeats for all rows on csv file.
Is there maybe some tips I should consider how to create this type of programm ?
Any tip would be great !
Thank You Very Much!
BB
Can you please clarify whether first value in a row in your file is date/time? 1392249600;EUR;CHF;USD;JPY;GBP
If yes, are you expecting that there will total 4 rows with the same date/time?
Or else you just need to go sequentially and use Line-1 as parent and then Line-2, Line-3, Line-4 as child and goes on... so that Line-5 becomes parent again?
To check whether country code is equivalent or not, you can use below kind of code. I am not 100% sure about your requirement, please correct me if you think this is not what you are looking for and I will try to answer you in other way:
package com.collections;
public class CountryCodeComparison {
public static void main(String[] args) {
//Read every row and sequentially insert value in CountryCode object.
//For ex. your row is: 1392163200;GBP;JPY;USD;CHF;EUR
String s1 = "1392163200;GBP;JPY;USD;CHF;EUR";
String [] array1 = s1.split(";");
CountryCode cc1 = new CountryCode(array1[1], array1[2], array1[1], array1[4], array1[5]);
//For ex. your row is: 1392076800;GBP;CHF;EUR;JPY;USD
String s2 = "1392076800;GBP;CHF;EUR;JPY;USD";
String [] array2 = s2.split(";");
CountryCode cc2 = new CountryCode(array2[1], array2[2], array2[1], array2[4], array2[5]);
if(cc1.equals(cc2)) {
System.out.println("Both CountryCode objects are equal.");
} else {
System.out.println("Both CountryCode objects are NOT equal.");
}
}
}
class CountryCode {
private String countryCode1;
private String countryCode2;
private String countryCode3;
private String countryCode4;
private String countryCode5;
public CountryCode(String countryCode1, String countryCode2,
String countryCode3, String countryCode4, String countryCode5) {
this.countryCode1 = countryCode1;
this.countryCode2 = countryCode2;
this.countryCode3 = countryCode3;
this.countryCode4 = countryCode4;
this.countryCode5 = countryCode5;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((countryCode1 == null) ? 0 : countryCode1.hashCode());
result = prime * result
+ ((countryCode2 == null) ? 0 : countryCode2.hashCode());
result = prime * result
+ ((countryCode3 == null) ? 0 : countryCode3.hashCode());
result = prime * result
+ ((countryCode4 == null) ? 0 : countryCode4.hashCode());
result = prime * result
+ ((countryCode5 == null) ? 0 : countryCode5.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CountryCode other = (CountryCode) obj;
if (countryCode1 == null) {
if (other.countryCode1 != null)
return false;
} else if (!countryCode1.equals(other.countryCode1))
return false;
if (countryCode2 == null) {
if (other.countryCode2 != null)
return false;
} else if (!countryCode2.equals(other.countryCode2))
return false;
if (countryCode3 == null) {
if (other.countryCode3 != null)
return false;
} else if (!countryCode3.equals(other.countryCode3))
return false;
if (countryCode4 == null) {
if (other.countryCode4 != null)
return false;
} else if (!countryCode4.equals(other.countryCode4))
return false;
if (countryCode5 == null) {
if (other.countryCode5 != null)
return false;
} else if (!countryCode5.equals(other.countryCode5))
return false;
return true;
}
}
I am getting an "Object Reference not set to an instance of an object" error when searching for an item (on Guid) that is selected from a datagrid. I have checked that the item does return the Guid correctly (by writing it to a label on the page), however in my linq query (i assume) i am comparing incorrectly.
ctx is the domaindatasource, I know the element im trying to remove exists.
private void medItemRemove_Click(object sender, RoutedEventArgs e)
{
MedicineInventory M = (MedicineInventory)medicineInventoryDataGrid.SelectedItem;
Guid Mid = M.MedicineInventoryId;
MedicineInventory toRemove = new MedicineInventory();
toRemove = (from a in ctx.MedicineInventories where (a.MedicineInventoryId == Mid) select a).Single();
ctx.MedicineInventories.Remove(toRemove);
ctx.SubmitChanges();
}
Rewrite your code as follows:
private void medItemRemove_Click(object sender, RoutedEventArgs e)
{
MedicineInventory M = (MedicineInventory)medicineInventoryDataGrid.SelectedItem;
Guid Mid = M.MedicineInventoryId;
MedicineInventory toRemove = (from a in ctx.MedicineInventories where (a != null && a.MedicineInventoryId == Mid) select a).SingleOrDefault();
if (toRemove != null){
ctx.MedicineInventories.Remove(toRemove);
ctx.SubmitChanges();
}
else { .... } // code if toRemove is null
}
Is a null at any point?
toRemove = (from a in ctx.MedicineInventories where (a != null && a.MedicineInventoryId == Mid) select a).Single();
I think your problem is happening because you're creating a new MedicineInventory.
Replace this:
MedicineInventory toRemove = new MedicineInventory();
With this:
var toRemove = ctx.MedicineInventories.Single(mi => mi.MedicineInventoryId == Mid);
Update:
When it retuns the error message "Sequence contains no elements" it's because EF could not find a row in the database with the same Guid you're using in the where clause. In this case and to avoid an exception, you can try this line of code:
var toRemove = ctx.MedicineInventories.SingleOrDefault(
mi => mi.MedicineInventoryId == Mid);
then use an if to delete if it's not NULL:
if(toRemove != null)
{
ctx.MedicineInventories.Remove(toRemove);
ctx.SubmitChanges();
}
else
{
// Only you know what to do! :-)
}
SingleOrDefault returns the only element of a sequence, or a default
value (NULL in this case) if the sequence is empty; this method
throws an exception if there is more than one element in the sequence.
Note: the way you're comparing the Guids is correct because == is overloaded on Guid so you don't need to compare the string representations.
See http://msdn.microsoft.com/en-us/library/system.guid.op_equality%28v=vs.110%29.aspx#Y474
I have the requiredFieldValidator configured for one of my columns and it works as expected for existing rows. When I tab thru, or click to begin editing a new row, the validator does not fire when moving off the column. When move off the new row (with no data in the column) so that it commits, and then move back to the row, now the validator works...but ONLY if I put some data in the editor, and then delete it.
In other words, for new rows, the requiredFieldValidator does not do anything until I actually type something in the column. If I leave a column blank it never fires, defeating the purpose of it. Interestingly, the example they provide (http://mleibman.github.com/SlickGrid/examples/example3-editing.html) exhibits the same problem.
This checks for both values being "". I believe this should return true since a validator could be a "required" validator.
this.isValueChanged = function () {
// this needs to validate if both are empty since a validator might be a "required" validator
if ($input.val() == "" && defaultValue == "")
return true;
else
return (!($input.val() == "" && defaultValue == "")) && ($input.val() != defaultValue);
};
Preferred method would be to create a custom editor so you aren't mucking with the core library.
I concur, just encountered this behavior myself.
Here is the solution.
Change this.isValueChanged function contents to the following.
if(($input.val().length > 0) && ($input.val() != defaultValue))
return true;
else if(($input.val() == defaultValue)&&($input.val().length > 0))
return true;
else if(($input.val().length == 0) && ((undefined === defaultValue )||(defaultValue == "")))
return true;
else
return false;
For some reason defaultValue is not set during the first interraction, my guess if you initialize it to "" you would not need to check for undefined.
At any rate defaultValue holds the previous value of the cell, so when it is empty and it is the first cell being edited it is undefined, after that it is set to "" for all other empty cells.
The problem is this function needs to tell the grid that the value has changed in order for the cell editor to validate the input. In the provided implementation the expression always returns false because
$input.val() == "" evaluates to true and then the expression
!($input.val() == "" && defaultValue == null)) evaluates to false
This means defaultValue is continuously undefined.
Hope that makes sense and my code helps you out.
Had the same problem and I believe that ideally defaultValue should be set to undefined or null, when it wasn't initialized. So I've modified TextEditor in a following way:
function TextEditor(args) {
var $input;
var defaultValue;
var scope = this;
this.loadValue = function (item) {
defaultValue = item[args.column.field] || null;
$input.val(defaultValue);
$input[0].defaultValue = defaultValue;
$input.select();
};
this.isValueChanged = function () {
return $input.val() != defaultValue;
};
....
setting default defaultValue to null and simplifying isValueChanged.
There is an error in the first else if of Roman, the return is false. Otherwise, any change in cell returns true even if the value has not been changed.
I tried this and it works.
this.isValueChanged = function () {
var attuale = $input.val();
if((attuale.length > 0) && (attuale != defaultValue))
return true;
else if((attuale == defaultValue)&&(attuale.length > 0))
return false;
else if((attuale.length == 0) && ((undefined === defaultValue )||(defaultValue == "")))
return true;
else
return false;
};
In most cases, validation methods I've overridden execute twice each time the parent field is changed. Everything still works, but the InfoLog displays double messages every time.
Is there any way to prevent this?
Thanks
public boolean validate()
{
boolean ret;
int exlowValue;
int lowValue;
int highValue;
int exhighValue;
str errorMessage;
;
ret = super();
//Make sure a numeric value was entered
if (ABC_RegExValidator::validateMe("integer", int2str (ABC_Checks_checkExtremeLow.value())))
{
//get the form values
exlowValue = ABC_Checks_checkExtremeLow.value();
lowValue = str2int(ABC_Checks_checkLow.valueStr());
highValue = str2int(ABC_Checks_checkHigh.valueStr());
exhighValue = str2int(ABC_Checks_checkExtremeHigh.valueStr());
//Extreme Low must be 0 or less than all others
if (exlowValue != 0)
{
//A non-zero value was entered; it must be less than all other fields
if ((exlowValue >= lowValue && lowValue > 0) || (exlowValue >= highValue && highValue > 0) || (exlowValue >= exhighValue && exhighValue > 0))
{
//Return an error
ret = checkfailed(strFmt("#ABC197", int2str(exlowValue)));
}
else
{
//Not greater than any other value
//Success!
ret = true;
} //Greater than all others?
}
else
{
//No errors
ret = true;
} // 0?
}
else
{
//Regular expression failed
//Return an error
ret = checkfailed("#ABC192");
} //Regular expression
return ret;
}
Your description of the problem is not really clear. One can override the valite method on a form control, the validate method on a form datasource and the validatefield method on the table. That's my knowledge of version 3.0.
And how do you mean the "parent field"? I presume the table field?
If I put info messages in each of these methods they only execute once when I modify a value. That's the case in 3.0. I don't know which version you're using.
Maybe you could be more precise about which validation method you're testing?