I have a VB class library with a test method. Which will return an Integer (sometimes Nothing will be returned).
Public Class Class1
Public Function testMethod() As Integer
'Some code here
Return Nothing
End Function
End Class
If I call the method in a VB Project, everything works great as expected. For example:
Dim output As String = testMethod().ToString() ' Works fine and output =""
But when I call the method by creating an object in C# application, it will throw error as null when the return value is Nothing.
VBTestLib.Class1 classObject = new VBTestLib.Class1();
string objectStringValue = classObject.testMethod().ToString(); // Error
Which means Nothing will be converted to null (null.ToString() is not allowed). Now consider the next example:
int objectIntValue = classObject.testMethod(); // objectIntValue = 0
Here Nothing will be converted to the default value of the int (0). I have extended the testing using dynamic then also the assigned value is 0. i.e.,
dynamic objectDynamicValue = classObject.testMethod();// objectDynamicValue = 0
So my question is, what is Nothing? How it will be converted when assigned to a C# type? Or shall I conclude that:
If a VB Method returns Nothing and the value is assigned to a C# variable of value type then the default value of method's return type will be assigned. And if it is assigned to a reference type variable then null will be assigned.
As I mentioned in the question (I assumed as well), Nothing Represents the default value of any data type (C# default(T)). For reference types, the default value is the null reference. For value types, the default value depends on whether the value type is nullable.
Here in my VB code the return value of the method is Integer (value type) So nothing will be its default value 0. That is why 0 is assigned to the dynamic type also. But it is not an alternative for null or it is not equivalent of null.
Related
According to Visual Studio this is not ok:
var foo = null;
But this is ok:
var foo = false ? (double?)null : null;
Why? Is the (double?)null affecting also the null in the else branch?
Implicitly typed variable declaration/assignment serves two purposes:
Decides the value of the variable, and
Decides the type of the variable.
Your first declaration has null for the value, with no way to figure out the type (it could be anything derived from System.Object, or a Nullable<T>). That is why it is an error.
Your second declaration pinpoints the type as Nullable<double> because of the cast. That is why C# allows it.
It goes without saying that double? foo = null would be much easier to read.
Because compiler cannot predict the type of null. Null can be assigned to any nullable datatype also to any reference type variable. So for implicit conversion, you have to cast null to some specific type.
var dt = (DateTime?)null; // This is correct
var dt1 = null; // This will throw compile time error.
The second example has double? type and the compiler knows it. According to documentation
It is important to understand that the var keyword does not mean
"variant" and does not indicate that the variable is loosely typed, or
late-bound. It just means that the compiler determines and assigns the
most appropriate type.
The compiler should ensure the type match with var.
var foo = null;
The compiler can't identify the type of foo.
var foo = false ? (double?)null : null;
Now the foo has double? type.
Assigning null to a var to a value, VS can't identify what type gonna be (double,int,bool etc). Var is commonly used when you don't know what type your value gonna be.
Your second declaration pinpoints the type as Nullable that's why you don't get an exception/error.
I would like to make use of out or ref parameters that may not be assigned prior to calling the function. The function then is responsible for checking whether the parameter exists, and if not, creates and returns a new object.
Here is some example C# code for what I'm trying to accomplish:
public virtual object MyFunction(out object myObject)
{
if (myObject == null)
myObject = new Object();
// do some more things here...
// maybe return myObject, or perhaps something else
return myObject;
}
I would like each of the four example function calls below to be considered valid:
Object x = new Object();
MyFunction(x); // x gets passed by reference
Object y = MyFunction(x);
Object z = MyFunction();
Object u = MyFunction(null);
I get an error on line 3 telling me that Out parameter 'list' might not be initialized before accessing. Attempting to give myObject a default value gives the error A 'ref' or 'out' parameter cannot have a default value.
Is there a way to use out parameters (pass by reference) and check to see if those references have been initialized before assigning them to anything?
No, this is not possible. If you use an out parameter then you are not permitted to read the value before assigning to the variable, for the reason the compiler has already told you. If you use ref then the parameter must be initialized before it is allowed to be passed in.
Return values are most of the time the right choice when the method doesn't have anything else to return.
It only stops the caller from having to declare the variable separately. Example:
int x1;
GetValue(out x1);
Declaring a variable:
int? x1 = GetValue();
You can read more about it in thi MSDN documentation.
When you pass a null as your out parameter, e.g. by using out _, the CLR will allocate temporary storage when you first use the parameter so there is no need for the initial check that won't compile.
Step over this line (there is no exception):
The call was double result = TestMethods.DoubleValue(2.5, out _);
I wrote two lines of code
1)
int i ;
MessageBox.Show(i.ToString());
2)
string str;
MessageBox.Show(str.ToString());
As I didn't initialize any of the variables and (1) is returning 0 but (2) throws an exception saying Object reference not set to an instance of an object
I can't understand that string is value type as int then this error is being shown.
....I can't understand that string is value type as int then this error is being occurred.
Who said string is value type? Its reference type and you have to give its value before using it, other wise you will get the error you are getting.
Whereas int is value type. Even if you do not initialize it, the are initialized by 0.
You can do this
string str = String.Empty;
str = SomeFunctionReturningString();
if (!String.IsNullOrEmpty(str)) //cause that function can also return null.
MessageBox.Show(str);
int is a value type, and string is a reference type, so they are different.
When you have a field (class-level variable), and you don't initialize the field value where you declare the field, then an int will be initialized with its default value which is 0. And a string field will get the default value of a reference type, which is the null reference.
When you have a local variable, you must assign a value to it before you use it. A local variable is one that is declared in the body of a method (or constructor, accessor etc.). Therefore your question was confusing, because it was not clear if you had fields or locals.
According to this a string (or String) is a reference type.
Yet given:
Type t = typeof(string);
then
if (t.IsByRef) ...
returns false
why?
Edit: After some quick testing, I'm obviously misunderstanding the purpose of IsByRef...
as even using a class name in place of 'string' ,returns false as well. I'm writing a generic class and want to test if one the types passed in when the generic is instantiate is a value or reference type. How does one test for this?
You should use IsValueType instead:
bool f = !typeof (string).IsValueType; //return true;
As for IsByRef, the purpose of this property is to determine whether the parameter is passed into method by ref or by value.
Example you have a method which a is passed by ref:
public static void Foo(ref int a)
{
}
You can determine whether a is pass by reference or not:
bool f = typeof (Program).GetMethod("Foo")
.GetParameters()
.First()
.ParameterType
.IsByRef; //return true
There are "reference types" -- for which we have !type.IsValueType -- and then there are types that represent references to anything -- whether their targets are value types or reference types.
When you say void Foo(ref int x), the x is said to be "passed by reference", hence ByRef.
Under the hood, x is a reference of the type ref int, which would correspond to typeof(int).MakeReferenceType().
Notice that these are two different kinds of "reference"s, completely orthogonal to each other.
(In fact, there's a third kind of "reference", System.TypedReference, which is just a struct.
There's also a fourth type of reference, the kind that every C programmer knows -- the pointer, T*.)
You want to check if it is a value type.
typeof(object).IsValueType :- false
typeof(int).IsValueType :- true
When declaring an int..
int A = 10;
why not do the following instead?
int A = new Int()
A=10;
are both the same?
Because int is syntax sugar for Int32 which is a value type. Incidentally, so is the constant value 10 (an instance of the value type Int32). That's why you don't need to use new to create a new instance, but rather making a copy of 10 and calling it A. And similar syntax works with reference types as well, but with the difference that a copy isn't made; a reference is created.
Essentially, you can think of 10 as a previously declared instance of Int32. Then int A = 10 is just setting variable A to a copy of value 10 (if we were talking about reference types then A would be set to a reference to the instance instead of a copy).
To better illustrate here's another example:
struct SomeValueType {
public SomeValueType(){
}
}
public static readonly SomeValueType DEFAULT = new SomeValueType();
Then you can just do this:
SomeValueType myValueType = DEFAULT; // no neeed to use new!
Now imagine that SomeValueType is Int32 and DEFAULT is 10. There it is!
You may have seen Java, where int and Integer are two different things, and the latter requires you to write new Integer(10).
In C# int is a special alias for Int32, and for all intents and purposes they are the same. Indeed, to create a new instance of any type you'd have to write new Int32() or something.
However, because integers are primitive types in C# (and most programming languages), there is a special syntax for integer literals. Just writing 10 makes it an Int32 (or int).
In your example you are actually assigning a value to the a variable twice:
int a = new Int32(); // First assignment, a equals 0
a = 10; // Second assignment, a equals 10
You might imagine that since the second assignment overwrites the first, the first assignment is not required.
In C# there are two kinds of types, "reference types" and "value types". (Pointers are a third kind of type but let's not get into that.)
When you use the default constructor of a value type, all you are saying is "give me the default value of this value type". So new int() is neither more nor less than just saying 0.
So your program is the same as:
int i = 0;
i = 10;
if you write youe code like
int A = new Int();
the variable 'A' is assigned by the default value of int, so you can use variable 'A' without assigning a value to it(in c# we cant use a variable without assigning a value to it)
when using the keyword new it will automatically call the default constructor, it will assign default values to the variables.
int A = new Int();
It declares and initializes A to 0.
Basically, the new operator here is used to invoke the default constructor for value types. For the type int, the default value is 0.
It has the same effect as the following:
int A = 0;