How to convert the following decimal? to String("F2") - c#

I have Decimal? Amount
In my model I have a value as #item.Sales, which I`m trying to write as #item.Sales.ToString("F2").
I`m having the message error Error 1 No overload for method 'ToString' takes 1 arguments
How can I achieve the above

If it's a nullable decimal, you need to get the non-nullable value first:
#item.Sales.Value.ToString("F2")
Of course, that will throw an exception if #item.Sales is actually a null value, so you'd need to check for that first.

You could create an Extension method so the main code is simpler
public static class DecimalExtensions
{
public static string ToString(this decimal? data, string formatString, string nullResult = "0.00")
{
return data.HasValue ? data.Value.ToString(formatString) : nullResult;
}
}
And you can call it like this:
decimal? value = 2.1234m;
Console.WriteLine(value.ToString("F2"));

if( item.Sales.HasValue )
{
item.Sales.Value.ToString(....)
}
else
{
//exception handling
}

Use the unary ? operator to run .ToString() only when there's an object
#item.Sales?.ToString("F2")
Or use the double ?? operator thus makes it non-nullable:
#((item.Sales??0).ToString("F2"))
This is better than #item.Sales.Value.Tostring("F2") because if you don't check for null value before using .ToString("F2") the code will break at runtime.

Related

Why must write O AS INT and can't write (INT)O

I've found in the Jon Skeet's book an example of using as operator with the types, which allows null value.
using System;
class A
{
static void PrintValueAsInt32(object o)
{
int? nullable = o as int?; // can't write int? nullable = (int?)o
Console.WriteLine(nullable.HasValue ?
nullable.Value.ToString() :
"null");
}
static void Main()
{
PrintValueAsInt32(5);
PrintValueAsInt32("some string");
}
}
I can't understand, why I can't write int? nullable = (int?)o? When I try to do that, I'm getting an exception.
Because the as operator is performing a check before cast.If types are not convertible to each other then it just returns null and avoids the InvalidCastException.
You are getting an exception when you try to perfom explicit cast because in the second call you are passing a string to the method which is not convertible to int?

Generic typed function: return a non-nullable value

I wrote this trivial utility function:
public static T isNull<T>(T? v, T d)
{
return v == null ? d : v.Value;
}
the purpose is to avoid annoying task like check for a member to be null, very common in reading a linq recordset. The problem is that it's throwing this error:
The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable< T>'
The error seems legit, anyway I wish I can do something like this:
int? myField = record.myField;
int myValue = isNull(myField, 0);
instead of:
int? myField = record.myField;
int myValue = myField == null ? 0 : myField.Value;
I feel like I'm missing some c# basic knowledge. Does exist a way to accomplish my task?
Generic constraints can be used on generic functions to limit the types that are permitted to be used to certain subsets, and this opens up possibilities for how you might use those types inside your method or class.
In this case, you can apply a constraint to T that limits it to a struct to resolve your specific compiler error.
public static T IsNull<T>(T? v, T d) where T : struct
{
return v == null ? d : v.Value;
}
However, another answer does correctly point out that you could opt to use the null coalescing operator ?? in this particular situation.
This is called null coalescing, and there is a built in operator to do it:
int myValue = record.myField ?? 0
While the other answers are good, presumably you'd like to write your method so it would work with both reference and value types. You can accomplish that by having two overloads, both with generic constraints.
public static T IsNull<T>(T v, T d) where T : class
{
return v ?? d;
}
public static T IsNull<T>(T? v, T d) where T : struct
{
return v.HasValue ? v.Value : d;
}
NOTE: Calling IsNull with a value type other than Nullable<T> will still not compile. e.g.
string myString = ...
Console.WriteLine(IsNull(myString, "foo")) // works
object myObject = ...
Console.WriteLine(IsNull(myMyObject, new object())) // works
DateTime? myDateTime = ...
Console.WriteLine(IsNull(myDateTme, DateTme.Now)) // works
int? myInt1 = ...
Console.WriteLine(IsNull(myInt1, DateTme.Now)) // works
int myInt2 = ...
Console.WriteLine(IsNull(myInt2, DateTme.Now)) // <-- compiler error

Type checking on Nullable<int>

If have the following method:
static void DoSomethingWithTwoNullables(Nullable<int> a, Nullable<int> b)
{
Console.WriteLine("Param a is Nullable<int>: " + (a is Nullable<int>));
Console.WriteLine("Param a is int : " + (a is int));
Console.WriteLine("Param b is Nullable<int>: " + (b is Nullable<int>));
Console.WriteLine("Param b is int : " + (b is int));
}
When i call this method with null as a parameter, the type check returns false for this parameter. For example this code
DoSomethingWithTwoNullables(5, new Nullable<int>());
results in this output:
Param a is Nullable<int>: True
Param a is int : True
Param b is Nullable<int>: False
Param b is int : False
Is there any way to preserve the type information when using a Nullable and passing null? I know that checking the type in this example is useless, but it illustrates the problem. In my project, I pass the parameters to another method that takes a params object[] array and tries to identify the type of the objects. This method needs to do different things for Nullable<int> and Nullable<long>.
Going straight to the underlying problem, no, you can't do this. A null Nullable<int> has exactly the same boxed representation as a null Nullable<long>, or indeed a 'normal' null. There is no way to tell what 'type' of null it is, since its underlying representation is simply all-zeros. See Boxing Nullable Types for more details.
conceptually, new Nullable<int> is null.
If we generalise, forgetting about Nullable<T>:
string s = null;
bool b = s is string;
we get false. false is the expected value for a type-check on a null value.
You can try using Reflection to achieve this. Relevant article here.
Unfortunately, null does not point to any specific memory location, and thus there is no metadata that you can associate with it to lookup the type. Thus, you cannot gain any additional information about the variable.
Unless I'm misunderstanding the question, you can get the type using GetType(). For example,
int? myNullableInt = null;
Console.WriteLine(myNullableInt.GetValueOrDefault().GetType());
If myNullableInt is null, a default value will be returned. Check the type of this returned value and, in this case, it will return System.Int32. You can do an If..else/Switch check on the returned type to perform the relevant action.
(int? is the same as Nullable<int>)
You can't do this, nor should you want to. Since Nullable<T> is a struct, value-type variables of this type have all the type information you need at compile time. Just use the typeof operator.
On the other hand, you might have a Nullable instance whose type you don't know at compile time. That would have to be a variable whose static type is object or some other reference type. Howver, because a Nullable<T> value boxes to a boxed T value, there's no such thing as a boxed Nullable<T>. That instance whose type your checking will just be a T.
This is why you get the same result for is int and is Nullable<int>. There's no way to distinguish between a boxed int and a boxed int?, because there is no boxed int?.
See Nulls not missing anymore for details.
As it has already been pointed out null has no type. To figure out if something is int? vs long? you need to use reflection to get information about something storing the type. Here is some code that you may be able to use as inspiration (not knowing exactly what you try to achieve the code is a bit weird):
class Pair<T> where T : struct {
public Pair(T? a, T? b) {
A = a;
B = b;
}
public T? A { get; private set; }
public T? B { get; private set; }
}
void DoSomething<T>(Pair<T> pair) where T : struct {
DoMore(pair);
}
void DoMore(params object[] args) {
Console.WriteLine("Do more");
var nullableIntPairs = args.Where(IsNullableIntPair);
foreach (Pair<int> pair in nullableIntPairs) {
Console.WriteLine(pair.A);
Console.WriteLine(pair.B);
}
}
bool IsNullableIntPair(object arg) {
var type = arg.GetType();
return type.IsGenericType
&& type.GetGenericTypeDefinition() == typeof(Pair<>)
&& type.GetGenericArguments()[0] == typeof(int);
}
If you execute the following code
DoSomething(new Pair<int>(5, new int?()));
DoSomething(new Pair<long>(new long?(), 6L));
you get the following output:
Do more
5
null
Do more
You can use typeof :
a == typeof(Nullable<int>) //true
a == typeof(int) //false

Null coalescing operator on decimal and decimal

I'm facing the following error while applying a null coalescing operator.
private decimal _currentImpulseId;
// ... later on used in public property getter as follows
public decimal CurrentImpulseId
{
get { return _currentImpulseId ?? 0M; }
set { _currentImpulseId = value; }
}
Following error is returned:
Operator '??' cannot be applied to operands of type 'decimal' and
'decimal'
Why doesn't this work? Does the null coalescing operator not work with decimals or am I missing something here? I know how I can work around this without using the operator, but this somewhat baffled me so I wonder if you know the correct answer on this?
Thanks!
You are getting this error because decimal is a value type, not a nullable value type (e.g. decimal?) or a reference type.
From MSDN:
...and is used to define a default value for nullable value types or reference types
The default value of a variable of type decimal is zero, so I am not quite sure why you would want to use this operator in this scenario.
Also, the backing field variable (_currentImpulseId) is not required as of .NET 3.0, since the introduction of auto-implemented properties means you can just write
public decimal CurrentImpulseId { get; set; }
Because decimal is a value type see HERE, you have to make it nullable.
Try
private decimal? _currentImpulseId;
// ... later on used in public property getter as follows
public decimal? CurrentImpulseId
{
get { return _currentImpulseId ?? 0M; }
set { _currentImpulseId = value; }
}

What are Nullable Types in C#?

int? _fileControlNo = null;
public int? FileControlNo
{
get { return _fileControlNo; }
set { _fileControlNo = value; }
}
I'm getting a syntax error when I assign null values to the above properties.
objDPRUtils.FileControlNo =sArrElements.Value(3)==null ? null : Convert.ToInt32(sArrElements.Value(3));
Please, can anyone explain to me why the error occurs if I'm able to set null value in valuetype object using Nullable Type.
The results of the conditional operators need to be of the same type or types that can be implicitly convertible to each other.
In your case you have a null and an Int32 - these violate that requirement.
If instead of an Int32 you return a nullable Int32, the null can be implicitly converted to this type and your code will work (or alternatively, cast the null to an int?).
Cast your null to int?
objDPRUtils.FileControlNo =sArrElements.Value(3)==null ? (int?) null : Convert.ToInt32(sArrElements.Value(3));
The conditional operator needs to return result of the same type and in your case its not possible for null
this should work
sArrElements.Value(3)==null ? (int?)null : Convert.ToInt32(sArrElements.Value(3));
Nullable types are exactly what they say they are: simple value types that can also store a null value.
I would suggest that you do not need the last line of code at all. you should be able to get away with:
objDPRUtils.FileControlNo =sArrElements.Value(3);
If you really want to assign another value in case of null, use the null coalescing operator ??
objDPRUtils.FileControlNo =sArrElements.Value(3)??0;
which in this case, would assign the value 0 to the FileControlNo in case of the right hand side being null.
Try to assign directly like this :
objDPRUtils.FileControlNo =sArrElements.Value(3);
Your code mixes types null and Int32 cannnot be mixed in this instance like that. They need to be of the same type.
If you use int.TryParse and only attempt to set the value on success you will achieve the same result and can use HasValue on the field to determine if its null or not which is how nullable types are used typically
Silly example
class Program
{
private static int? _fileControlNo;
static void Main(string[] args)
{
string[] sArrElements = new string[] { "1", "2", "3", null };
int result;
if (int.TryParse(sArrElements[3], out result))
{
FileControlNo = result;
}
if (_fileControlNo.HasValue)
{
// do something here
}
}
public static int? FileControlNo
{
get { return _fileControlNo; }
set { _fileControlNo = value; }
}
}
you will note that your code inside the test for HasValue in this case will never execute because _fileControlNo cannot be set because tryParse always fails (change the indexer and that will change).

Categories

Resources