A value of type 'Null' can't be returned from the method 'fetchById' because it has a return type of 'Location' - flutter

static Location fetchById(int id) {
List<Location> locations = Location.fetchAll();
for (var i = 0; i < locations.length; i++) {
if (locations[i].id == id) {
return locations[i];
}
}
return null;
}
// if the condition is not true then return null when I try to return null or false it gives the error 'A value of type 'Null' can't be returned from the method 'fetchById' because it has a return type of 'Location'.

With null-safety feature in the dart language, you have to explicitly tell if you want to make a value nullable.
Define the return type with a ?, so dart knows that return value can be null.
static Location? fetchById(int id)
{
/// function body
}

Related

forEach -> return true; // error The return type 'bool' isn't a 'void', as required

Hello I try to make null safety migration, but I have an error with a forEach loop who return return true. I don't know how to write correctly in null stafety. Thank you
String sanitize(
String input, List<String> possibleStart, List<String> possibleEnd) {
final String start = possibleStart.join("|");
final String end = possibleEnd.join("|");
final RegExp exp = RegExp("(?<=$start)(.*?)(?=$end)");
final Iterable<Match> matches = exp.allMatches(input);
matches.forEach((match) {
input =
input.replaceFirst(match.group(0)!, match.group(0)!.replaceAll(",", "§").replaceAll(":", "ø").replaceAll("/", "å"));
return true; // error The return type 'bool' isn't a 'void', as required by the closure's context dart flutter
});
return input;
}
function forEach isn't supposed to return anyting, you can see it from iterable.dart
void forEach(void action(E element)) {
for (E element in this) action(element);
}

type 'Null' is not a subtype of type 'bool' in type cast

I have Created a Map<String,bool>(in which the key are of type String and the values are of type Boolean) in flutter and When I want to use the bool values in if condition it give me error saying "A nullable expression can't be used as a condition.
Try checking that the value isn't 'null' before using it as a condition."
When I use "as bool" then the error is gone but the program is not executed properly and give me the error in the pic
//this is the code
Map<String, bool> _userFilters = {
"gluten": false,
"lactose": false,
"vegan": false,
"vegetarian": false,
};
List<Meal> filteredMeal = DUMMY_MEALS;
void saveFilters(Map<String, bool> filteredData) {
setState(() {
_userFilters = filteredData;
filteredMeal = DUMMY_MEALS.where(
(meal) {
if (_userFilters['gluten']as bool) { // _userFilter['gluten'] is giving error
return false;
}
if (_userFilters['lactose']as bool) {
return false;
}
if (_userFilters['vegan']as bool) {
return false;
}
if (_userFilters['vegetarian'] as bool) {
return false;
}
return true;
},
).toList();
});
}
No need to cast your map entries to booleans. use an exclamation mark at the end of your variable (e.g, _usedFilters['gluten']!) to treat it as non-nullable.
Rewrite all your conditions like this (if you're sure that the value won't be null):
if (_userFilters['gluten']!) {
return false;
}
if (_userFilters['lactose']!) {
return false;
}
if (_userFilters['vegan']!) {
return false;
}
if (_userFilters['vegetarian']!) {
return false;
}
From Dart.dev:
“Casting away nullability” comes up often enough that we have a new
shorthand syntax. A postfix exclamation mark (!) takes the expression
on the left and casts it to its underlying non-nullable type.

Cannot return Null from a non-nullable type function

This is the error message I am getting:
The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
on the following code:
Product findProductById(String prodId) {
_productsList.firstWhere((element) {
return prodId == element.id;
});
}
I want to find the Product by its id but if its not found what should I return?
You're not returning inside the findProductById function:
Product findProductById(String prodId) {
return _productsList.firstWhere((element) {
return prodId == element.id;
});
}
From Dart 2.12 and up, we need to specify whether if a type is nullable or non-nullable.
In your case, you should add '?' question mark after the type name Product as you can see below, which will tell the compiler that your function can return a nullable product.
Also you forgot to return the filtered product from the productList.
Product? findProductById(String prodId) {
return _productsList.firstWhere((element) {
return prodId == element.id;
});
You can return a empty Product it's not found.
Product findProductById(String productId) {
return productList.firstWhere((element) => element.id == productId,
orElse: () => Product() // make a empty product using default constructor);
}

Passing null vs nothing to named parameters

This is my class:
class Source {
final int value;
Source({this.value = 1}) {
print("source = $value");
}
}
This is how I'm passing values:
Source(value: null); // prints null
Source(); // prints 1
The question is if I am passing null to value in first call, why doesn't it print 1, aren't they equivalent?
In your definition you are creating a default parameter.
value is being defined as 1 and will be the default value in the absence of any other value being assigned to that parameter. When you actively provide it null as a value, it takes precedence over the default.
#adlopez15 is the correct answer.
But if you want null to result in 1 you can do this:
class Source {
final int value;
Source({int value}) : value = value ?? 1 {
print("source = ${this.value}");
}
}

Entity Framework - dynamic query

I'm creating a dynamic expression builder and trying to implement the 'like' function. Before writing my own I've searched for any existing function and found one close to my need. After several experiments I couldn't bring it to run for types other than string.
When I pass a parameter of type int then I get this error:
Method 'System.String ToString()' declared on type 'System.String' cannot be called with instance of type 'System.Int32'
My code looks like this:
private static MethodCallExpression GetLowerCasePropertyAccess(MemberExpression propertyAccess)
{
//return Expression.Call(Expression.Call(propertyAccess, "ToString", new Type[0]), typeof(string).GetMethod("ToLower", new Type[0]));
return Expression.Call(Expression.Call(propertyAccess, typeof(string).GetMethod("ToString", System.Type.EmptyTypes)), typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
}
private static readonly MethodInfo ContainsMethod = typeof(String).GetMethod("Contains", new Type[] { typeof(String) });
public static Expression<Func<T, bool>> Create<T>(string propertyName, ComparisonOperators comparisonOperator, dynamic comparedValue1, dynamic comparedValue2 = null)
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.MakeMemberAccess(parameterExpression, typeof(T).GetProperty(propertyName));
ConstantExpression constantExpression = Expression.Constant(comparedValue1, comparedValue1.GetType());
Expression expressionBody = null;
switch (comparisonOperator)
{
...
case ComparisonOperators.Contains:
//var indexOf = Expression.Call(memberExpression, "IndexOf", null, Expression.Constant(comparedValue1, typeof(string)), Expression.Constant(StringComparison.InvariantCultureIgnoreCase));
//expressionBody = Expression.GreaterThanOrEqual(indexOf, Expression.Constant(0));
expressionBody = Expression.Call(GetLowerCasePropertyAccess(memberExpression), ContainsMethod, Expression.Constant(comparedValue1.ToLower()));
break;
}
return Expression.Lambda<Func<T, bool>>(expressionBody, new ParameterExpression[] { parameterExpression });
}
I'm not sure I fully understand what you're doing, but I think your error is caused by this line:
return Expression.Call(Expression.Call(propertyAccess, typeof(string).GetMethod("ToString", System.Type.EmptyTypes)), typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
Which will always try and call the ToString method for a string type, so if you try and use an Int32 property, you're then trying to call String.ToString(), since the implementation of ToString() will be different for different types and the two implementations will not necessarily be compatible, you'll get the exception you're seeing:
Method 'System.String ToString()' declared on type 'System.String' cannot be called with instance of type 'System.Int32'
From what it looks like you're doing, I think this may be what you're after:
return Expression.Call(Expression.Call(propertyAccess, propertyAccess.Type.GetMethod("ToString", System.Type.EmptyTypes)), typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
Which will use the correct implementation of ToString (with type obtained from propertyAccess.Type).
Linq to entities doesn't support .ToString method. For converting numeric values to string you need to use SqlFunctions.StringConvert method. I've fixed your code and now you can do like on string and numeric columns:
private static Expression GetConvertToStringExpression(Expression e)
{
// if property string - no cast needed
// else - use SqlFunction.StringConvert(double?) or SqlFunction.StringConvert(decimal?);
Expression strExpression = null;
if (e.Type == typeof(string))
strExpression = e;
var systemType = Nullable.GetUnderlyingType(e.Type) ?? e.Type;
if (systemType == typeof(int)
|| systemType == typeof(long)
|| systemType == typeof(double)
|| systemType == typeof(short)
|| systemType == typeof(byte)) // continue
{
// cast int to double
var doubleExpr = Expression.Convert(e, typeof (double?));
strExpression = Expression.Call(StringConvertMethodDouble, doubleExpr);
}
if (systemType == typeof (decimal))
{
// call decimal version of StringConvert method
// cast to nullable decimal
var decimalExpr = Expression.Convert(e, typeof (decimal?));
strExpression = Expression.Call(StringConvertMethodDecimal, decimalExpr);
}
return strExpression;
}
private static MethodCallExpression GetLowerCasePropertyAccess(Expression propertyAccess)
{
var stringExpression = GetConvertToStringExpression(propertyAccess);
if (stringExpression == null)
throw new Exception(string.Format("Not supported property type {0}", propertyAccess.Type));
return Expression.Call(stringExpression,
typeof (string).GetMethod("ToLower", Type.EmptyTypes));
}
private static readonly MethodInfo StringConvertMethodDouble = typeof (SqlFunctions).GetMethod("StringConvert",
new Type[] {typeof (double?)});
private static readonly MethodInfo StringConvertMethodDecimal = typeof(SqlFunctions).GetMethod("StringConvert",
new Type[] { typeof(decimal?) });
I have just made something like that:
public Expression<Func<T,bool>> BuildContainsExpression<T>(MemberExpression memberExp, object comparedValue)
{
var parameter = Expression.Parameter(memberExp.Member.DeclaringType, "x");
var method = typeof(string).GetMethod("Contains", types: new[] { typeof(string) });
var comparison = Expression.Equal(
Expression.Call(
method: method,
instance: memberExp,
arguments: Expression.Constant(comparedValue)),
Expression.Constant(true)
);
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
}
And it builds an expression like below:
x.Language.Contains("tr")
(with my dynamic parameters)