Using a derived class in c# out parameters [duplicate] - c#

In c# I am trying to implement a method which I can use to bind data to any control I pass to it (provided of course the control is derived from a databoundcontrol object)
given the method
public void CTLBindData(ref DataBoundControl ctl){ ... }
I get an error when trying to pass derived control to the function
for example the following code
DropDownList lister = new DropDownList();
CTLBindData(ref lister);
Generates a conversion error
Ok I can accept that, but the following confuses me (probably because I am used to c++ not c#)
CTLBindData(ref (DataBoundControl)lister);
in this case I get the error
"A ref or out argument must be an assignable variable"
For clarification A Dropdownlist inherits from a list control which inherits from a DataBoundControl
This makes no sense to me I should be able to pass in any object that has been derived from a databound control. It seems that the explicit typecast is causing the problem.
Any clues as to what I am doing wrong?
DC

Do the cast prior to calling the method like this:
DataBoundControl countrol = (DataBoundControl)lister;
CTLBindData(ref control);
C# requires that any ref parameters be of the exact type (no polymorphism) and the reference of that type must be assignable. This is why you must create the reference via explicit cast in a separate step so the method has a reference of the correct type to which a value can be assigned.
For more information about this topic please see Why do ref and out parameters not allow type variation? by Eric Lippert:
If you have a method that takes an "X"
then you have to pass an expression of
type X or something convertible to X.
Say, an expression of a type derived
from X. But if you have a method that
takes a "ref X", you have to pass a
ref to a variable of type X, period.
Why is that? Why not allow the type to
vary, as we do with non-ref calls?

Use a generic function with the appropriate type parameter constraint:
public void CTLBindData<TControl>(ref TControl ctl)
where TControl : DataBoundControl
{ ... }
The type is inferred directly in the call, and the ocnstraint ensures that the control is of the appropriate type.

Andrew Hare is correct, but in this case, you may not even want to be using the ref. Objects in C# are already passed by reference*. (As opposed to value types, which are not passed by reference unless you use the ref keyword.) There are very few cases that I can think of where you'd actually need to pass a reference type in that way. Without the ref, your original code should work just fine.
**Not really, but it's easier to understand that way if you come from a non-C# background. The reference is actually passed by value. There is an excellent article on the exactly how this all works.*

Andrew Hare answered very well.
Your object must need something inside to use REF or OUT. For example: could be null.
DropDownList lister = new DropDownList();
lister = null;
CTLBindData(ref lister);

Related

Why does a method that returns a type result in an implicit typing of dynamic?

In the following code snippet why does the implicitly typed variable be determined as a dynamic instead of the method's return type of FluentClass?
public static class DynamicTest
{
public class FluentClass
{
public FluentClass SomeMethod(dynamic arg)
{
return this;
}
}
public static void Main()
{
dynamic data = new { Data = 1 };
var fluentClass = new FluentClass();
// fluentClass variable is typed FluentClass
var methodResult = fluentClass.SomeMethod(data);
// methodResult variable is typed dynamic
}
}
Why does a method that returns a type result in an implicit typing of dynamic?
Because that's the best the compiler can do, given the information it has.
The reason methodResult is dynamic is that the entire expression used to initialize it is dynamic. And that's the case, because data is dynamic.
When you use dynamic, you're telling the compiler to not resolve types at compiler time. Instead, they should be resolved according to the normal compiler rules, but at run-time.
The fluentClass variable could hold some implementation of FluentClass that contains an overload that matches the run-time type of the argument data. In that case, a different implementation of SomeMethod() could be called, returning a different type.
You've told the compiler to defer type resolution to run-time, so it can't force things back into a strongly-typed context unless you tell it explicitly what type things are. In your example, it can't, so the type remains dynamic.
Note that you might have thought that the compiler would identify the one overload you've provided, based on its parameter type of dynamic. But that's not how dynamic works. The dynamic parameter affects only the implementation of the method, i.e. the code in its body. As far as calling the method goes, the parameter is essentially object. It's just that when the parameter value is used in the method body, it has the features of dynamic.
Another way to think of dynamic is that it accepts any object as input (like object), but then allows you to use any member of that object that you believe exists (if it doesn't exist an exception will be thrown at run-time). Using dynamic defers the compiler logic downstream, i.e. for the output of any usages of the dynamic variable, but doesn't affect the input, i.e. the assignment of that variable.
Note also that even if the method call is completely unambiguous, e.g. a static method where there's only one method with that name, you'll still get a dynamic result. Once you start using dynamic, it sticks with you until you provide an explicit cast to get back to a known type.
Related reading:
Very similar to your question, if not actually duplicates:
Why does a method invocation expression have type dynamic even when there is only one possible return type?
Why does this method keep returning dynamic despite the return type in the signature?
Why doesn't this string.Format() return string, but dynamic?
More general discussion of dynamic:
What is the 'dynamic' type in C# 4.0 used for?
C# 4: Real-World Example of Dynamic Types

Cast object into appropriate type for overloaded methods

Say I have a method that is overloaded such as void PrintInfo(Person) and void PrintInfo(Item), and so on. I try to invoke these methods by passing in an Object.
I'm wondering why it is giving me an error when I do this; aren't all classes inherited from Object? I want to avoid doing an if/switch statement where I check which type the Object is before calling the appropriate method.
What do you guys think is the best approach in this case?
All Persons are objects , but not all objects are Persons. Because of this you can pass a Person to a method that accepts an object but you can't pass an object to a method that requires a Person.
It sounds like you have some common bit of functionality between various objects that you want to use. Given this, it would be best to find either a common ancestor that has all of the functionality that you need, or an interface that they all implement (that again provides everything that you need).
In the case of printing, you may just need the ToString method. In that case, you can just have the method accept an object and call ToString on it. (That's what many print methods do, such as Console.WriteLine.
You need to understand that because C# is a statically typed language (barring dynamic) the particular overload that is chosen (called overload resolution) is determined at compile time, not run time. That means that the compiler needs to be able to unequivocally determine what type your argument is. Consider:
Object foo;
foo = "String";
foo = 5;
PrintInfo(foo); // Which overload of printinfo should be called? The compiler doesn't know!
There are a few ways to solve this- making foo of type dynamic is one- that will cause the correct overload to be chosen at compile time. The problem with that is that you lose type safety- if you don't have an appropriate overload for that type, your application will still compile but will crash when you try to print the unsupported type's info.
An arguably better approach is to ensure that foo is always of the correct type, rather than just Object.
As #Servy suggests, another approach is to attach the behavior to the type itself. You could, for instance, make an interface IHasPrintInfo:
public interface IHasPrintInfo { String PrintInfo { get; } }
and implement that interface on all items whose info you might print. Then your PrintInfo function can just take an IPrintInfo:
public void PrintInfo(IPrintInfo info) {
Console.WriteLine(info.PrintInfo);
}
here its ambiguate for compiler; compiler can't figure out which version of method (Person/Item) you are intended to call.

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.

Why can't I use a "Type" to create a new variable in C#?

int number = 5;
Type dynamicType = number.GetType(); // dynamic type is "int"
dynamicType x = (number as dynamicType);
How would you expect the compiler to treat the variable x later in the code? It wouldn't know anything about it... so it couldn't resolve any method calls etc.
Basically what you're after is dynamic typing which is supported in C# 4 with the "dynamic" pseudo-type:
int number = 5;
dynamic d = number;
// Calls to d are resolved at execution time, so this compiles:
d.ThisWillThrowAtExecutionTime();
Type is an object that represents information about a type. It's not a designator for a variable saying it is of that type.
SomeObject myObject = new SomeObject();
Type t = myObject.GetType();
SomeObject myOtherObject = (SomeObject)Activator.CreateInstance(t);
The ability to do this goes all the way back to .Net v1.0. No need for fancy dynamic typing or anything like that.
Constructing objects with more complex constructors takes a bit more work, but it's the same idea.
You can, just not directly. You can use reflection. Basically you get the fully qualified name of the type (from the Type object) and then call CreateInstance method from an assembly object that contains that type. It should be quite simple to get the assembly reference of the current instance...
I think the Assembly.GetExecutingAssembly() method will do it.
I've written a little about this quite some time ago in a post at: http://frater.wordpress.com/2007/06/24/instantiating-classes-through-reflection-using-c-dynamic-object-creation/
That might help you out some more, though the focus was also on compiling of c# code from within a c# program, to allow for the use of C# as a scripting language, so some of the details might not be completely relevant.
Hope that helps!
Because it wouldn't make any sense.
What would you do next?
The purpose of a cast is to assign the casted object to a variable of the type that you casted it to. In this case, you wouldn't be able to do that, since a field must have a static type at compile time.
What are you trying to do?
dynamicType is an object of type "Type" that holds the Type meta-data information of type "int" hence dynamicType is and instance or object and not a qualified type so you cannot perform instantiation on that.
So, AFAIK you can't use the Type to instantiate 'basic' data types such as int.
You could use it to create objects though:
Object x=Activator.CreateInstance(dynamicType)
The issue is, if you want to call methods or access fields on a dynamic type, you have to use reflection. See the Type class documentation for instructions.

(C#) why does Visual Studio say it's an object while GetType says it's a Func<object>?

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.

Categories

Resources