I have a COM object in C#:
Class myClass = new Class;
IPClass myPointer = null;
myPointer = (IPClass) myClass.GetMyPointer();
bool myBool = myPointer.DoSomething();
myClass.GetMyPointer() in C# is returning a dynamic type. In the original code where the COM object is defined, myClass.GetMyPointer returns a pointer to an interface IPClass in C++.
When I test my C# dll, I could not get myBool. VS always says that myBool does not exist in the current context. But DoSomething was always performed. I just could not get the returning value back. I have tried to temporarily stop garbage collection from C# and it did not make any difference.
Anyone has any suggestions?
Try this and see what it returns:
System.Diagnostics.Debug.WriteLine("calling DoSomething()");
System.Diagnostics.Debug.WriteLine((myPointer.DoSomething()).GetType().Name);
System.Diagnostics.Debug.WriteLine("finished call to DoSomething()");
Related
C# newbie question here. The following code (taken from the book "C# From Novice to Professional" by Christian Gross, Apress) gives an error:
worksheet.Add("C3", CellFactories.DoAdd(worksheet["A2"], worksheet["B1"]));
The reason is that the method DoAdd() does not accept the given arguments.
public static Func<object> DoAdd(Func<object> cell1, Func<object> cell2) {...}
VS claims that both args in the method call above are of type object whereas the method accepts only Func<object>. But the value of both worksheet elements is of type Func<object>:
worksheet.Add("A2", CellFactories.Static(10.0));
where this Static method just returns the given value:
public static Func<object> Static(object value) { return () => value; }
// return type= Func<object>
When I cast worksheet["A2"] as Func<object>, the code does work.
But there is something I don't understand. The type of the object instance is Func<object>. I have used the GetType() method to see proof of this, and compare the object types of the original elements to that of the cast object (which IS accepted):
Console.Writeline(worksheet["A2"].GetType());
// now cast to the correct type (why can't it do that implicitly, btw?)
Funk1 = worksheet["A2"] as Func<object>;
Console.Writeline(Funk1.GetType());
.. and they are ALL identical! (Type = System.Func'1[System.Object])
And even when I use the .Equals() method to compare both types, it returns true.
Yet, VS sees the first object instance as type object in the method call. Why? Why does the called method 'see' the argument as a different type than the GetType() returns?
(and if so, what good is the GetType() method?)
Thanks a lot for your advice/comments! (It's kinda hard to learn the language if the book examples give an error and you don't see the reason - hence, got the vague impression that something is wrong either with GetType() or VS.)
You need to understand the difference between dynamic typing and static typing. The indexer for your worksheet object most likely has a static type of object.
public object this[string cell]{get{...}set{...}}
Because all objects in C# inherit from type object, the object reference stored in a cell can be a reference to any object.
That is, because a delegate (such as Func<T>) is an object, it can be stored in an object reference:
Func<object> func = ()=>return "foo";
object o = func; // this compiles fine
And the compiler can figure this all out, because it understands implicitly that a derived class can be stored in a reference to a base class.
What the compiler cannot do automatically, is determine what the dynamic type, or run time type of an object is.
Func<object> func = ()=>return "foo";
object o = func; // this compiles fine
func = o; // <-- ERROR
The compiler doesn't know that the object stored in o is actually of type Func<object>. It's not supposed to keep track of this. This is information that must be checked at run time.
func = (Func<object>)o; // ok!
The above line of code compiles into something that behaves similarly to this:
if(o == null)
func = null;
else if(typeof(Func<object>).IsAssignableFrom(func.GetType()))
__copy_reference_address__(func, o); // made up function! demonstration only
else throw new InvalidCastException();
In this way, any cast (conversion from one type to another) can be checked at run time to make sure it's valid and safe.
Others have given accurate and detailed answers, but here I will try to explain in simple language.
When you write worksheet["A2"] you really are calling a member function of worksheet
worksheet has a member function named [] that accepts a string and returns an object
The signature of the member function [] looks like object this[string id]
So the function worksheet["A2"] returns something that is an object. It could be an int or a string or many other things. All the compiler knows is that it will be an object.
In the example, you have it returning a Func<object>. This is fine, because Func<object> is an object. However, you then pass the result of that function in as a parameter to another function.
The problem here is that the compiler only knows that worksheet["A2"] returns an object. That is as specific as the compiler can be.
So the compiler sees that worksheet["A2"] is an object, and you are trying to pass the object to a function that does not accept object as a parameter.
So here you have to tell the compiler "hey dummy, that's a Func<object>" by casting the returned object to the correct type.
worksheet.Add("C3", CellFactories.DoAdd(worksheet["A2"], worksheet["B1"]));
can be re-written as
worksheet.Add("C3", CellFactories.DoAdd((Func<object>)worksheet["A2"], (Func<object>)worksheet["B1"]));
Now the compiler knows that, even though the [] function returns an object, it can treat it like a Func<object>.
side note: You're probably doing too much on one line. That may be hard for people to read in the future.
Why does the called method 'see' the argument as a different type than the GetType() returns?
The compiler only knows that worksheet[] returns an object. The compiler can not call GetType() on it at compile time.
What good is the GetType() method?
There are quite a few uses and abuses of the GetType() method, but that is an entirely different discussion. ;)
In summary, the compiler does not assume anything about types. This is a good thing because you get a compile time error when you try to fit this square peg into a round hole. If the compiler did not complain, this error would surface at run-time, which means you would probably need a unit test to detect the problem.
You can get around this problem by telling the compiler "I know for a fact that this thing is a round peg, trust me." and then it will compile.
If you lie to the compiler, you will get a run-time error when that code is executed.
This is called "static typing". The opposing philosophy is called "dynamic typing" where type checks are done at run-time. Static vs dynamic is a lengthy debate and you should probably research it on your own if you're interested.
VS claims that both args in the method call above are of type object whereas the method accepts only Func. But the value of both worksheet elements is of type Func
Yes, but the declared type is object. The compiler can't know that the actual runtime type will be Func<object>, so an explicit cast is necessary.
Today I am reading article and article shows the code snippet:-
string s1 = "Something";
string s2 = (string)s1.Clone();
if ((object).ReferenceEquals(s1, s2))
throw new Exception("But I need to know!");
Code snippet throws an error why? I can't understand what happened under a hood in CLR.
My question is a string or reference type casting create a new object or not?
From this MSDN Link, It specifically states The return value is not an independent copy of this instance; it is simply another view of the same data.
and that there is little reason to call it directly.
So, in short the Clone() method does not create a new copy. Type casting does not influence the instance of the data in memory, it merely provides another way of interpreting the same data.
The correct way to call a static method is to directly call that method on the type. class.Method(). By wrapping the type in parenthesis the compile considers this a cast of an instance.
Change this line ...
if ((object).ReferenceEquals(s1, s2))
... to this ...
if (object.ReferenceEquals(s1, s2))
I'm writing a routine in C# that is designed to copy an object after casting into the object that contains the routine.
Sample Code:
public void SetObjectData(object objectInDisguise)
{
Member objectToCopy = (Member)objectInDisguise;
_field1 = objectToCopy._field1;
_field2 = objectToCopy._field2;
}
Null pointer exceptions and weak variable names notwithstanding, is there any way that I can simply cast the object to the Member class and copy the reference to this into my current Member object?
I tried something like:
this = objectToCopy;
but this is read-only, so the compiler didn't let me. Just wondering if anyone knew how one could manage this.
I have a VBScript app calling COM-registered C# objects. I am able to pass in a COM object to a COM call, as well as receive either a primitive or a COM object back, but I can't do both at the same time! If I try retrieving any value back from the call while also passing in a COM object, I get the exception "Invalid procedure call or argument"
Dim foo
Set foo = Server.CreateObject("Foo")
foo.SetProperty(1)
Dim bar
Set bar = Server.CreateObject("Bar")
Dim return
Set return = bar.Do(foo)
If that last line is simply bar.Do(foo) it works fine.
Also, whether it is
Set return = bar.Do(foo)
or
return = bar.Do(foo)
causes the same error in this case.
My COM classes are classes with only methods exposed, and implementing an interface. I'm getting this error by dealing with only ints, longs, and Strings.
I'm a bit rusty in this area but if your method is returning an int or string shouldn't your code then read:
return = bar.Do(foo)
instead of
Set return = bar.Do(foo)
"return = bar.Do(foo)" should work, as long as Bar.Do is actually returning something. How is Bar.Do defined?
using c#, vs2008, winforms
If i am passing a parameter via a property to a child form from a parent form, or infact via a property to any class, and the the paramater im passing in C# is a reference type created in the parent form,
does it get passed as a ref or value by default ?
Eg if i pass a dataset via a property.
And if it does get passed by value, can you make it passed by ref via a property ?
Or should i just pass it via a method paramater, is that better practice ?
Basicaly i want to retrieve a populated object back to the parent form, and feel passing by ref an object that is created in the parent form is better.
For reference types, a reference to the variable is passed by value. Unless, of course, you use the ref or out keywords in C# to alter that behaviour.
That means that a DataSet-valued property passes, in actual fact, a reference to a DataSet instance, and passes it by value.
Jon Skeet's "C# in Depth" is a great reference (no pun intended) on these matters.
It is important to note that pass by reference in C# has a specific meaning. In the case of a property, the property ends up pointing to the same address as that of the object it was set to. In the case of passing objects to a function, C# uses pass reference by value semantics. That means that the reference itself is copied, so a new pointer points to the same address as the object that was passed. This prevents a function from nullifying any original pointer by setting its parameters to null. To actually pass an original reference, the 'ref' keyword must be used:
class SomeClass
{
public object MyObjectProperty { get; set; }
}
var someClass = new SomeClass();
object someObject = new object();
someClass.MyObjectProperty = someObject; // Makes MyObjectProperty point to the same location as someObject
In the following case, reference by value semantics are used:
void MyMethod(object someObject)
{
someObject = null;
}
object someObject = new object();
MyMethod(someObject);
Console.WriteLine(someObject == null); // Prints false
In the following case, actual pass by reference semantics are used:
void MyMethod(ref object someObject)
{
someObject = null;
}
object someObject = new object();
MyMethod(ref someObject);
Console.WriteLine(someObject == null); // Prints true
The first thing to understand is that, in .Net, a variable can be either a value type (e.g int) or a reference type (a class). Value type variables point directly to a value in memory, whereas reference type variables point to a memory location.
By default, parameters are passed by value. However, remember that the 'value' of a reference type is actually its location in memory. So even though it's called passing by value, you are really passing a reference to a particular class.
C# does not pass by reference in the same way that C++ does. It is more accurate to say that it passes by reference value (for reference types anyways).
Read this by Jon Skeet