Const vs. Static in a switch statement [duplicate] - c#

This question already has answers here:
Passing objects by reference vs value
(3 answers)
Closed 7 years ago.
I'm converting some old VB.NET to C#. Among the more minor issues I've come across is how to handle passing large objects into methods. In VB we would use the ByRef keyword, like this:
Friend Sub New(ByRef Parent As WorkSheet)
'INITIALIZE OBJECT
Me.WS = Parent
pColorId = 64
pZoomScale = 100
End Sub
But in C# there are a long list of limitations that make this not possible. For instance, refs cannot have default values, you cannot pass in a constant, null or this because those are read-only.
Is there a simple solution to this? Or do you just ignore it and pass everything without a qualifier and the compiler just does the right thing?

You don't need to pass objects by ref, all classes are reference types and don't need to be passed by ref in your case.
Passing Reference Type Variables
A variable of a reference type does not contain its data directly; it
contains a reference to its data. When you pass a reference-type
parameter by value, it is possible to change the data pointed to by
the reference, such as the value of a class member.
Do not confuse the concept of passing by reference with the concept of
reference types. The two concepts are not the same. A method parameter
can be modified by ref regardless of whether it is a value type or a
reference type. There is no boxing of a value type when it is passed
by reference.

In C#, all references to classes that derive from object are copied to the method. When you pass an object reference to a method, you operate on the actual object passed in.
The ref keyword that you refer to is a reference to a reference, and you only need to use that if you plan to change the reference itself that is passed in (in your example, you'd need ref if you planned to set Parent to null, and wanted this to apply outside of the method).

Related

Passing an object as a constructor parameter seems to be passing by reference instead of value

I'm having strange issue where I am creating a new object which contains a parameter for another object (paramObj) I use through my function. So, paramObj is used in an object constructor, but it ends up being altered after the constructor is called. Since C# is pass by value, I'm not sure why this is happening.
My code:
void MyFunction(List<string> filesets)
{
foreach(Fileset fs in filesets)
{
//At this point, fs.allFiles.Count is 30. The MyNewObject class
//takes a Fileset as a parameters and eventually clears the
//Fileset.allFiles List, making the count 0.
MyNewObject tmpObj = new MyNewObject(fs, null, "default");
//At this point, fs.allFiles.Count is 0, but I expect it to be 30
}
}
The MyNewObject class simply clears the allFiles list contained within a Fileset class. Why is that showing up after the constructor if C# is pass by value?
You´re right in that everything in .NET is passed by value. Even references - and this is what fs actually is - are passed by value. Thus, when you pass fs around your method will have a copy of that reference. This reference however references the exact same object, making any change on that reference modifiying the backing object also.
So in your constructor you have a second reference to the FileSet-instance referenced by fs.
This more or less leads to the conclusion, that objects are effectivly passed by reference.
There´s no simple way to circumvent this. It depends on why you even modify anything on that object within the constructor at all. You could try to copy the provided object referenced by fs within your constructor, e.g. by implementing IClonable within FileSet or by providing a copy-constructor within that class or whatever. However depending on what FileSet and it´s members are you will need some deep copy of the provided instance.
For further reading on how to make a deep copy of an object look here: Deep cloning objects
Normally, all the objects are passed by reference as parameter to the method. On the other hand most of the primitive data types such as integer, double, Boolean etc. are passed by value.

Can I set the value of decimal variable within an extension method? [duplicate]

This question already has answers here:
Impossible to use ref and out for first ("this") parameter in Extension methods?
(6 answers)
Closed 7 years ago.
I have created a void extension method which can be used with decimal data types. I wanted to be able to modify the this parameter variable inside the scope of the method. This is the code for my extension method:
public static void SetAndConvertIfHasValue(this decimal assignTo, double? valueToAssign)
{
if (valueToAssign.HasValue)
assignTo = (decimal)valueToAssign.Value;
else
assignTo = 0m;
}
However, when I call it:
data.MyDecimalToSet.SetAndConvertIfHasValue(nullableDouble);
data.MyDecimalToSet is not set to the value in nullableDouble if it has one.
In debug if I step into the extension method, assignTo is changed to the correct value, this change just doesn't bubble up to data.MyDecimalToSet.
At this point I have decided to use a standard method rather than an extension method as a solution to this problem, however I was curious as to why this doesn't work? And whether there is a way around it, or if it simply is impossible?
This doesn't work because when you pass a variable to a method, a copy of that variable is passed. When you operate on that copy, you will only be changing the copy.
Note that this will happen regardless of whether the variable is a reference or a value type. However, if you pass a reference type, you can change the contents of the reference type, since the reference passed to the method will be copied, but it will still reference the original object.
(decimal is a value type, so that last point does not apply to it.)
You are doing it the right way if you use a standard method instead.

Getting the type of Dynamic variable [duplicate]

This question already has answers here:
get the Type for a object declared dynamic
(2 answers)
Closed 8 years ago.
I am accessing a COM object and a method returns a dynamic variable. I do not have the implementation of the method that returns the dynamic variable and I need to cast it to the appropriate type so that I can use it in my class.
So I would like to know if there is a way to find the underlying type of a dynamic variable during runtime.
The dynamic variable is the value returning from a COM function so the UnWrap doesnt work and GetType() returns COMObject type.
thanks
If the object being returned can be one of many Types then you're best to keep using it as a dynamic and only trying to access methods and properties you know will exist (I'd expect the COM method to have some indication of how to use the dynamic it returns).
var canBeLiterallyAnything = ComMethod();
canbeLiterallyAnything.MethodDocsSayExists();
var propVal = canBeLiterallyAnything.SomeProperty;
Of course, if all of the possible Types all implement the same interface, you could cast to that interface.
var typeSafeReference = (ISharedInterface)canBeLiterallyAnything;
If you know that the COM method returns a specific Type but just don't know what that Type is then for the purpose of investigation you can call GetType() and either write it to console or set a breakpoint and inspect it. This will let you then update your code to include a cast to that Type (which would minimise the impact of the use of dynamic, but also introduce the risk of a bad cast if other Types can be returned).
var type = canBeLiterallyAnything.GetType();
// e.g. If the above returns a Type of 'SpecificType', then you can update code to
var typeSafeReference = (SpecificType)canBeLiterallyAnything;
It should be noted that the COM method might not return a concrete Type, it might be returning an anonymous object, in which case there is no casting you can do so you'll have to just keep using it as a dynamic and only access properties/methods you know exist.

Are ILists passed by value?

Passing Value Type parameters to functions in c# is by value unless you use the ref or out keyword on the parameter. But does this also apply to Reference Types?
Specifically I have a function that takes an IList<Foo>. Will the list passed to my function be a copy of the list with copy of its contained objects? Or will modifications to the list also apply for the caller? If so - Is there a clever way I can go about passing a copy?
public void SomeFunction()
{
IList<Foo> list = new List<Foo>();
list.Add(new Foo());
DoSomethingWithCopyOfTheList(list);
..
}
public void DoSomethingWithCopyOfTheList(IList<Foo> list)
{
// Do something
}
All parameters are passed by value unless you explicitly use ref or out. However, when you pass an instance of a reference type, you pass the reference by value. I.e. the reference itself is copied, but since it is still pointing to the same instance, you can still modify the instance through this reference. I.e. the instance is not copied. The reference is.
If you want to make a copy of the list itself, List<T> has a handy constructor, that takes an IEnumerable<T>.
You're not alone; this confuses a lot of people.
Here's how I like to think of it.
A variable is a storage location.
A variable can store something of a particular type.
There are two kinds of types: value types and reference types.
The value of a variable of reference type is a reference to an object of that type.
The value of a variable of value type is an object of that type.
A formal parameter is a kind of variable.
There are three kinds of formal parameters: value parameters, ref parameters, and out parameters.
When you use a variable as an argument corresponding to a value parameter, the value of the variable is copied into the storage associated with the formal parameter. If the variable is of value type, then a copy of the value is made. If the variable is of reference type, then a copy of the reference is made, and the two variables now refer to the same object. Either way, a copy of the value of the variable is made.
When you use a variable as an argument corresponding to an out or ref parameter the parameter becomes an alias for the variable. When you say:
void M(ref int x) { ...}
...
int y = 123;
M(ref y);
what you are saying is "x and y now are the same variable". They both refer to the same storage location.
I find that much easier to comprehend than thinking about how the alias is actually implemented -- by passing the managed address of the variable to the formal parameter.
Is that clear?
The list is passed by reference, so if you modify the list in SomeFunction, you modify the list for the caller as well.
You can create a copy of a list by creating a new one:
var newList = new List<Foo>(oldList);
your list is passed by reference. If you want to pass a copy of the list you can do:
IList<Foo> clone = new List<Foo>(list);
if you add/remove elements in clone it won't modify list
but the modifications of the elements themselves will be taken into account in both lists.
When you pass reference type by value (without ref or out keywords) you may modify this reference type inside this method and all changes will reflect to callers code.
To solve your problem you may explicitly create a copy and pass this copy to your function, or you may use:
list.AsReadOnly();
When passing reference types, you pass the reference. This is an important concept.
If you pass a reference
byref, you pass the reference (pointer) directly.
byval, you pass a copy of the reference (pointer).
A reference is not the instance referenced. A reference is analagous to a pointer.
To pass a copy of the instance of a referencetype, you first must make a copy yourself and pass a reference to the copy. As such then you will not be modifying the original instance.

Anonymous Types

I have a Dictionary(TKey, TValue) like
Dictionary<int, ArrayList> Deduction_Employees =
new Dictionary<int, ArrayList>();
and later I add to that array list an anonymous type like this
var day_and_type = new {
TheDay = myDay,
EntranceOrExit = isEntranceDelay
};
Deduction_Employees[Employee_ID].Add(day_and_type);
Now how can I unbox that var and access those properties ??
First, you aren't unboxing the type. Anonymous types are reference types, not structures.
Even though you can technically create instances of the same type outside of the method they were declared in (as per section 7.5.10.6 of the C# 3.0 Language Specification, which states:
Within the same program, two anonymous
object initializers that specify a
sequence of properties of the same
names and compile-time types in the
same order will produce instances of
the same anonymous type.
) you have no way of getting the name of the type, which you need in order to perform the cast from Object back to the type you created. You would have to resort to a cast-by-example solution which is inherently flawed.
Cast-by-example is flawed because from a design standpoint, every single place you want to access the type outside the function it is declared (and still inside the same module), you have to effectively declare the type all over again.
It's a duplication of effort that leads to sloppy design and implementation.
If you are using .NET 4.0, then you could place the object instance in a dynamic variable. However, the major drawback is the lack of compile-time verification of member access. You could easily misspell the name of the member, and then you have a run-time error instead of a compile-time error.
Ultimately, if you find the need to use an anonymous type outside the method it is declared in, then the only good solution is to create a concrete type and substitute the anonymous type for the concrete type.
There are several ways.
Since the comments seems to indicate that I suggest you do this, let me make it clear: You should be creating a named type for your object since you intend to pass it around.
First, you can use Reflection, which another answer here has already pointed out.
Another way, which tricks .NET into giving you the right type is known as "cast by example", and it goes something like this: You need to pass your object through a generic method call, which will return the object as the right type, by inferring the right type to return.
For instance, try this:
private static T CastByExample<T>(T example, object value)
{
return (T)value;
}
and to use it:
var x = CastByExample(new { TheDay = ??, EntranceOrExit = ?? }, obj);
for the two ?? spots, you just need to pass something fitting the data type for those properties, the values will not be used.
This exploits the fact that multiple anonymous types containing the exact same properties, of the same type, in the same order, in the same assembly, will map to the same single type.
However, by this time you should be creating a named type instead.
An anonymous type has method scope. To pass an anonymous type, or a collection that contains anonymous types, outside a method boundary, you must first cast the type to object. However, this defeats the strong typing of the anonymous type. If you must store your query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.
Source: http://msdn.microsoft.com/en-us/library/bb397696.aspx
No you can't. You can only access the properties by using reflection. The compiler has no way of knowing what the type was, and since it's an anonymous type, you can't cast it either.
If you are using .NET 1.x - 3.x, you must use reflection.
If you use .NET 4.0, you could use a dynamic type and call the expected properties.
In neither case do you need to unbox; that's for value types. Anonymous types are always reference types.

Categories

Resources