|
dojohansen wrote: and it would not compile if you did the same assignment using return values instead of output parameters.
It would compile if you cast the return value to SomeA
SomeA a = (SomeA) Method2();
dojohansen wrote: But in my original code the assignment I'm trying to do is known to be safe, as you can verify since the same assignment done from a return value rather than an out parameter builds just fine (and indeed runs fine).
I guess I used the wrong example - here's what you are trying to do
interface ISome {}
class SomeA : ISome {}
class SomeB : ISome {}
void Method()
{
ISome some = SomeB();
Method2(out some);
}
void Method2(out SomeA some)
{
some = new SomeA();
}
The problem here is ISome need not refer to SomeA, it could refer to any class that implements ISome, but Method2 is expecting SomeA. In fact, the code wouldn't compile even if you removed the out keyword.
The code would compile if you changed the parameter of Method2 to out ISome some instead.
Casting to SomeA when calling Method2 would also work, but not if the parameter is out . The variable you're passing as out needs to be assignable, and the cast expression is not assignable.
And about it working for return types, welcome to the world of covariance and contravariance[^]. Return values are covariant, method parameters are contravariant, which means that return values could be more derived than what the caller expects, whereas method parameters could only be equal or less derived than the caller's parameters.
|
|
|
|
|
I'm afraid you are still not getting my question. I'm fully aware that it doesn't compile if I use the specific type that the function actually assigns to the out parameter as the declared type of that parameter. But my point is that I see absolutely no reason why it should not.
Again, if you simply frame the issue as "why should (output/ref) parameters have different assignability compared to return values?" it should become clear that your reply does not answer the question.
One detail while I'm at it: When using the output parameter it makes little sense to initialize the variable; just declare it. But let's not go off topic on that one.
|
|
|
|
|
Hmm. This was your original code sample.
public interface SomeInterface { }
class A : SomeInterface
{
public SomeInterface Field;
void foo()
{
Parse(out this.Field);
}
static public void Parse(out A something)
{
something = new A();
}
}
You're asking why the compiler doesn't allow this.Field to be passed as an output parameter to Parse, which takes a type that implements SomeInterface as a parameter, right? Whereas it works if Parse returns an instance of A and foo stores it in this.Field, right?
dojohansen wrote: Again, if you simply frame the issue as "why should (output/ref) parameters have different assignability compared to return values?"
No, that's not the issue. The issue is that method parameters have different assignability compared to return values.
It is because method parameters and return values have different rules when it comes to what type they can be. Regardless of the fact that out parameters are used to simulate return values, they are method parameters to the language, and are therefore subject to method parameter rules.
The(simplified) rules are
1. Return values can be more derived than what the caller expects.
ISomeInterface isi = Parse(...);
<Any_Type_That_Implements_ISomeInterface> Parse(...) {}
2. Method parameters should be the same or less derived than what the caller is passing
Parse(this.Field);
void Parse(<ISomeInterface_Or_Any_Class/Interface_ISomeInterface_derived_from> something){}
A little thinking will tell you why the rules exist.
ISomeInterface isi = new A();
A a = isi;
By passing this.Field to Parse , you are trying to do what the second statement in the above snippet is trying to do, and that's why the compiler is not allowing it. Using a return value has semantics similar to the first statement, and that's why it works.
Hope this helps
|
|
|
|
|
Hi,
Thanks for trying to help out. I think I get it. I disagree with your claim that my code is trying to perform that illegal assignment. "Field" is of the interface type (the less derived type), and the out parameter is of the concrete type that implements the interface type. The only assignment that would ever be attempted if that code ran (forgetting for a second the fact that it does not compile!) is the first of your two assignments, which is indeed legal.
In C# an out parameter cannot be used in the method declaring it unless that method has assigned it; it is considered unassigned, just like any local variable that has been declared but not initialized. Because of this "strictly one-way" behavior, an out parameter *could* logically speaking support the same assignability rules as return values. A ref parameter on the other hand could not, since it can be used in both directions, thus resulting in a downcast (to a more derived type) that is implicit yet unsafe.
But then I thought for a moment about what the compiler would actually do with output and ref parameters, and it occured to me that it probably generates exactly the same IL for both! After all, the only difference is that you're not allowed to use the out parameter in the declaring method, and you are required to always assign it, both of which can be verified by the compiler but result in the same IL code (or no IL code at all if changing a ref parameter to an out parameter results in a build error - changing an out to a ref however will never cause a build error).
I think I've therefore arrived at the following conclusion:
1) There are no reasons at the abstract level why a formal out parameter could not be more derived than it's corresponding actual parameter. If the language allowed callers to use foo(out obj) where obj is declared as "object", no unsafe casting would ever result regardless of how derived the formal parameter is, e.g. foo(out int n) or foo(out CryptoStream s).
2) There are some (probably pretty good) practical reasons why parameters should all follow the same rules. If they do, formal parameters must necessarily be less derived than actual ones.
|
|
|
|
|
Yeah, the issue is that out is simply an attribute affixed to a parameter, it doesn't affect type checking in any way.
As you said, the error goes away if rewrite Parse to take the interface as the out parameter (instead of the concrete type). You only lose the ability to specify that the method sets instances of type A (or one of its derived types) to the out parameter.
Great discussion though
|
|
|
|
|
Hi all,
as stated in the subject line can we say function overloading as polymorphism??
According to some oops authors overloading is compile time and overriding is runtime polymorphism!!!
However, if we visit the definition of Grady Booch for Polymorphism is "One interface many implementation",which means that overloading is not a type of polymorphism! (as interface gets changed when we change the function parameter)
What do you say?
What is your opinion?
Deep
Happy coding
|
|
|
|
|
Overloading and overriding are different concepts; the later being more the polymorphism.
class EggSample
{
void Method()
{
}
void Method(string param)
{
}
void Method(int count, string param)
{
}
}
That is the overloads - same method name with a different signature in a class.
Overriding would be:
class HenOther : EggSample
{
void Method(string param)
{
}
}
It's like an inbred hillbilly family - they all look the same but each behaves in a slightly odd way.
Panic, Chaos, Destruction.
My work here is done.
|
|
|
|
|
Well that's not actually an override. What you did is method hiding, and the compiler will warn you and say you should put the "new" keyword on the method declaration if the hiding was intended.
Polymorphism is incredibly powerful and can greatly simplify the design of many a thing. It is, in my view, the single most important concept of OOP, even more important than encapsulation (though that is certainly important too).
Virtual methods are said to be "late bound" and non-virtual methods "early bound". What this means is that when the compiler creates the CIL (formerly MSIL) code for your C# or other .net code, for non-virtual methods it will create code that invokes a specific method. Which method is called is determined by looking at the declared type of the reference to the object (or the type indicated for static methods, which obviously can never be virtual or behave polymorphically).
The above is NOT polymorphic. Given this code:
EggSample obj = new HenOther();
obj.Method("param");
We are allowed to do this of course, because HenOther extends EggSample. However, the compiler will create code to invoke EggSample.Method(), not HenOther.Method(), because "obj" (my reference) has the declared type EggSample, even though it's run-time type is in fact HenOther.
Virtual methods on the other hand are handled differently. The compiler will generate code to look up the method to call at run-time from what's called the type's VMT - Virtual Method Table. This means there's a small performance hit involved in invoking virtual methods, but that the method called is determined by the run-time (actual) type of the object rather than the declared type.
This is extremely useful in lots of situations, because it allows us to divide and conquer in ways we never could without it. Imagine you want to create a data transformation system that can read input files, process the input and compute statistics or whatever, and transform flat files to xml and lots of stuff. You'd have a gazillion ways to do this of course, but one approach could be to build a tree structure where each node in the tree represents some operation on the data and the structure of the tree creates a breakdown of the work. You could then use polymorphy to great effect. You could use either an interface (which is of course inherently polymorphic) or a simple base class, like this:
abstract public class ProcessingNode
{
public List<processingnode> Children = new List<processingnode>();
virtual public void PreProcess(Data d) {}
virtual public void PostProcess(Data d) {}
public void Execute(Data d)
{
PreProcess(d);
foreach (ProcessingNode node in Children) node.Execute(d);
PostProcess(d);
}
}
Purists might argue that the Pre- and Post-process methods should be abstract, but I prefer providing a default implementation that does nothing. Then, if I derive a node that only does postprocessing (that is, processing that occurs AFTER the subtree has finished processing) I don't need to override the PreProcess method (I would have to if it was abstract in the base class.
Now you'd have a very extensible model where you can derive lots of different processing nodes that perform various operations. For example, you could create a Selection node that selects some subset of data, and an Aggregate node that computes an aggregate on the selected data. The Selection node would do something like d.Select(...); on preprocess and d.Unselect(); in the postprocess method. The subtree inserted into the selection node would process only the current selection rather than all the data.
As a final example, you could create an "UpperCase" processing node as easily as this:
public class Upper : ProcessingNode
{
override public void PreProcess(Data d)
{
d.Selection.Text = d.Selection.Text.ToUpper();
}
}
assuming, for brevity, that the Selection has a text representation you may modify. As you can see, the base class can make use of new processing nodes you add without any of this code knowing about the types. All it knows is that the object has a capability to preprocess and postprocess, and there is no need to write a bunch of code to call this method if the operation is "Upper" and another if it's something else. You could go ahead and add encryption nodes, image decoders/converters, translation nodes, indexing nodes, sniffers looking for product names or companies, and a million other things. And if you released your system as an assembly, as long as the base class is public, other people could add new types of processing nodes as well.
And that's the power of polymorphism!
|
|
|
|
|
I didn't do that right
I was coding 'freehand' without the use of an IDE or compiler and I was writing some java stuff last night where the above (with the correct syntax for String ) would work as described.
But polymorphism it is, that's the whole point of it. Different classes being able to accept the same methods and behave differently depending on their own internals.
woteva.ToString(); will behave in the correct way for the class woteva - whatever it may be.
But then overloading is also a form of 'lotsaforms' .
Panic, Chaos, Destruction.
My work here is done.
|
|
|
|
|
Indeed, you didn't do that right. Not sure what you mean by "polymorphism it is", but I hope you're not clamining that the code you posted results in polymorphic behavior. It doesn't, as you can verify for yourself using this code:
public class A
{
public void M1() { Debug.WriteLine("A.M1()"); }
virtual public void M2() { Debug.WriteLine("A.M2()"); }
}
public class B : A
{
new public void M1() { Debug.WriteLine("B.M1()"); }
virtual public void M2() { Debug.WriteLine("B.M2()"); }
}
class Program
{
static public void Main(string[] args)
{
B b = new B();
A b_declared_as_a = b;
b.M1();
b.M2();
b_declared_as_a.M1();
b_declared_as_a.M2();
}
}
Now, we have two references to a single object instance. The non-virtual method M1() is called based on the *declared* type of the object - thus A.M1() executes when we invoke b_declared_as_a.M1() - because that reference is declared as type A.
The virtual method M2() however always results in running B.M2(), because that's the run-time type of the object and the declared type is irrelevant for virtual method calls.
ToString() is indeed virtual, and that's great since it lets you do things like string formatting more easily. The default implementation returns the type name, so if you call ToString() on b above you get the name. If you override the method you get whatever you return in the overridden method. Obviously there's no code in object.ToString() that somehow obtains a reference to the instance of type B and calls ToString() on it. The reason it works is because the code generated for ToString() isn't a normal method call, but a lookup in the VMT for the type (B in this example) and then a dynamic invokation. This allows you to write code today that call methods you only create in the future, perhaps in another assembly.
Method hiding however is really not much more than having two types that both have a method with the same name.
|
|
|
|
|
Overloading is just calling different methods with the same name by different parameter signatures. I wouldn't call this polymorphism. Really not. As said, this is resolved at compile time.
Overriding a virtual method however is the mainstay of polymorphism.
Regards,
Rob Philpott.
|
|
|
|
|
anybody else here who like to share his/her thought on this topic??
|
|
|
|
|
I completely agree with Booch. While people may use words whatever way they like as far as I'm concerned, "polymorphism" loses it's meaning if the interface changes. Technically there's no difference between methods f() and g() compared to f() and f(int). They're simply different methods. Overloads are useful, but only for the human users of the code. If I offer multiple ways to do the same thing, such as specify a timeout using either the number of milliseconds (int) or a TimeSpan, it is obviously easier for the user to cope with two methods with the same name instead of getting potentially far more method names in his intellisense list. But that is also the extent of it's usefulness - it has nada to do with polymorphism/virtual method invokation/late binding.
I suppose my opinion ought to be expected if you read my entries elsewhere in this thread.
|
|
|
|
|
Hey guys, please consider the following code
...
RequestSize = Int32.Parse(FinalLength);
strMessage = strMessage.Remove(0, 1);
string command = strMessage.Substring(0, RequestSize);
strMessage = strMessage.Remove(0, RequestSize);
ProcessCommand(command);
This works perfectly, unless the command variable is upwards of 30000 characters long
If the command is that big, both the SubString and Remove methods just do nothing. When debugging this and hitting those calls, its like it just breaks away from those methods and then nothing. The UI thread is not getting tied up so its not just taking some time to do it...
How can I fix this?
Thanks
<edit>Please see reply to Rob Philpott for more detail</edit>
Harvey Saayman - South Africa
Software Developer
.Net, C#, SQL
you.suck = (you.Passion != Programming & you.Occupation == jobTitles.Programmer)
1000100 1101111 1100101 1110011 100000 1110100 1101000 1101001 1110011 100000 1101101 1100101 1100001 1101110 100000 1101001 1101101 100000 1100001 100000 1100111 1100101 1100101 1101011 111111
modified on Thursday, April 9, 2009 5:14 AM
|
|
|
|
|
Strange, my understanding is that strings can be huge in .NET, so I don't know why this 30,000 ceiling comes in.
I can offer no solution to that, but might suggest that rather than 'Removing' parts from such a huge string you either iterate over it to get what you need or just copy substrings.
Regards,
Rob Philpott.
|
|
|
|
|
Rob Philpott wrote: I can offer no solution to that, but might suggest that rather than 'Removing' parts from such a huge string you either iterate over it to get what you need or just copy substrings.
Here's what happens exactly
After i get a server response from a TCP connection, the listener thread sends back all that data via a callback. Now one of these callbacks may have more than one command in it.
Each command starts with ln=[length of command][terminator]
So I loop to find a ln= , when I do I remove it, and then parse the length of the command to come. Then I take that command out (sub string it so i can pass it to another method), and remove it from the pool of commands so that the loop may continue in case there's another command to execute. Here's the full methods code
private void ProcessMessage(string CommandPool)
{
RawResponseReceived(CommandPool);
while (CommandPool != string.Empty)
{
if (CommandPool.StartsWith("ln="))
{
CommandPool = CommandPool.Remove(0, 3);
int RequestSize = -1;
string FinalLength = string.Empty;
while (Int32.TryParse(CommandPool[0].ToString(), out RequestSize))
{
FinalLength += RequestSize.ToString();
CommandPool = CommandPool.Remove(0, 1);
}
RequestSize = Int32.Parse(FinalLength);
CommandPool = CommandPool.Remove(0, 1);
string command = CommandPool.Substring(0, RequestSize);
CommandPool = CommandPool.Remove(0, RequestSize);
ProcessCommand(command);
}
else
{
Console.Write("Char removed - " + CommandPool[0]);
CommandPool = CommandPool.Remove(0, 1);
}
}
}
NOTE: I just changed some of the variable names to make it more readable
The reason these strings are so big sometimes, is that I'm getting binary data in it aswel. Can this be causing the problems?
Harvey Saayman - South Africa
Software Developer
.Net, C#, SQL
you.suck = (you.Passion != Programming & you.Occupation == jobTitles.Programmer)
1000100 1101111 1100101 1110011 100000 1110100 1101000 1101001 1110011 100000 1101101 1100101 1100001 1101110 100000 1101001 1101101 100000 1100001 100000 1100111 1100101 1100101 1101011 111111
|
|
|
|
|
Hmm. Ok. I wouldn't have thought binary would have caused an issue, but if you're receiving data back from a TCP stream, why don't you process it in a stream manner?
So, rather than waiting for the whole response and turning into a huge string which your iteratively break down into seperate parts, you do this as the response comes in. This way, you don't have the memory footprint of the large string, and you can start processing when the data starts arriving rather than when its finished.
Something like ReadByte() check = 'l', ReadByte() check = 'n', ReadByte() check = '=', then read to terminator to extract the command length, parse that. Then, keep reading each command.
Only a suggestion, and I'm still at a loss why your having problems with your current solution.
Regards,
Rob Philpott.
|
|
|
|
|
Thanks, I'll have a look at doing it like that...
I'd prefer this way though, it seems easier and less error prone
Harvey Saayman - South Africa
Software Developer
.Net, C#, SQL
you.suck = (you.Passion != Programming & you.Occupation == jobTitles.Programmer)
1000100 1101111 1100101 1110011 100000 1110100 1101000 1101001 1110011 100000 1101101 1100101 1100001 1101110 100000 1101001 1101101 100000 1100001 100000 1100111 1100101 1100101 1101011 111111
|
|
|
|
|
I for one have difficulty believing that what you say happens actually does happen.
But, even if your code is correct and the string you're interested in should eventually be extracted from it you should never ever manipulate large strings in .NET. They are immutable. And that means that whenever you modify a string you are in fact allocating a new string and copying all the not-modified characters from the original. That's not cool.
For an extreme display of the difference in performance, try running this code in a console.
Stopwatch w;
static void time(string msg)
{
Console.WriteLine(msg + ", elapsed time = " + w.Elapsed.ToString());
w = Stopwatch.StartNew();
}
static void Main(string[] args)
{
int count = 1000*1000;
string s = "";
StringBuilder sb = new StringBuilder();
w = Stopwatch.StartNew();
for (int i=0; i < count; i++) s += ".";
time("Using string");
for (int i=0; i < count; i++) sb.Append(".");
time("Using StringBuilder");
}
You may find you wish to adjust the count so that the "string" implementation will ever finish, although the StringBuilder will do this pretty quickly.
Obviously it is a very extreme example - the statement s += "."; hides an inner loop copying all the characters of the old s into the new s. Even worse, it puts huge pressure on the memory manager as it allocates a million strings (count), and these eventually become huge, forcing the GC to collect and reallocate, collect and reallocate all the time. You will see that with small strings both methods run in a short time, but percentage-wise the StringBuilder will always be a lot faster.
The way the StringBuilder does this internally is by representing the string as a char[] and keeping track of which chars actually have valid data in them. Just like an ArrayList it doubles in size when it reallocates, so starting from 16 (you'd get slightly better performance if you passed the correct capacity to the StringBuilder constructor as then it wouldn't need to reallocate ever) it must reallocate just fourteen times to get to a million, against one million for the string method.
|
|
|
|
|
Hey there
Yeah i realize the string builder is allot more efficient, i usually just get the concept working using stings and then if necessary replace it with string builders.
To try and fix this problem replaced the string with a string builder, here is the current code
private void ProcessMessage(string CommandPool)
{
RawResponseReceived(CommandPool);
StringBuilder sbCommandPool = new StringBuilder(CommandPool);
while (sbCommandPool.ToString() != string.Empty)
{
if (sbCommandPool.ToString().StartsWith("ln="))
{
sbCommandPool = sbCommandPool.Remove(0, 3);
int RequestSize = -1;
string FinalLength = string.Empty;
while (Int32.TryParse(sbCommandPool[0].ToString(), out RequestSize))
{
FinalLength += RequestSize.ToString();
sbCommandPool = sbCommandPool.Remove(0, 1);
}
RequestSize = Int32.Parse(FinalLength);
sbCommandPool = sbCommandPool.Remove(0, 1);
string command = sbCommandPool.ToString().Substring(0, RequestSize);
sbCommandPool = sbCommandPool.Remove(0, RequestSize);
ProcessCommand(command);
}
else
{
Console.Write("Char removed - " + sbCommandPool[0]);
sbCommandPool = sbCommandPool.Remove(0, 1);
}
}
}
the problem persists, when the debugger hits string command = sbCommandPool.ToString().Substring(0, RequestSize); the UI thread becomes active again and the next lines aren't getting executed
Harvey Saayman - South Africa
Software Developer
.Net, C#, SQL
you.suck = (you.Passion != Programming & you.Occupation == jobTitles.Programmer)
1000100 1101111 1100101 1110011 100000 1110100 1101000 1101001 1110011 100000 1101101 1100101 1100001 1101110 100000 1101001 1101101 100000 1100001 100000 1100111 1100101 1100101 1101011 111111
|
|
|
|
|
But... when you call ToString().SubString() you are of course using string again.
The fact that the UI thread becomes active is probably no indication of the state of your program. Visual Studio need not hang in order for your program to be busy.
However, doing this a single time on a string of size on the order of thirty thousand characters should not take long at all.
I wrote a simple console app to test and with a string of 30000 characters and taking 28000 of them for the substring it takes about 0.01 seconds on my (cheapass) machine.
class Program
{
static void Main(string[] args)
{
int size = 30000;
int take = 28000;
char[] chars = new char[size];
for (int i = 0; i < size; i++) chars[i] = '.';
string s = new String(chars);
Stopwatch w = Stopwatch.StartNew();
s = s.Substring(0, take);
Console.WriteLine(w.Elapsed);
Console.ReadKey(true);
}
}
I'm at a complete loss as to how this can happen. Nor can I reproduce the problem you're having. So it seems like it might be time to reinstall your system... or at least try to take the code to another computer and compile it there and see if you still have the problem.
Should all this fail, you can always attempt using a char[] instead and implement "substring" yourself; after all it's a simple matter.
void substring(char[] src, char[] dest, int startIndex, int count)
{
for (int i=0; i < count; i++)
dest[i] = src[i + startIndex];
}
Obviously you should add range checking to that if you want it proper.
|
|
|
|
|
Re-reading your previous postings makes me wonder if what really happens is that your program terminates. I had not noticed that you're calling this on another thread, but depending on how you do this, what type of application it is, and what framework version you are using, it migth be possible.
I don't know all the different possibilities and how they're handled, but I do remember we created threads ourselves in our asp.net application like this: Thread t = new Thread(new ThreadStart(method)); t.Start(); and this actually killed the application if any unhandled exception occured during method. [EDIT] I forgot to say this was on the 1.x Framework and I believe it has changed since. [/EDIT]
In other words, if we invoked String.SubString and passed any invalid arguments, such as a length that requires going beyond the end of the string (try to take 30001 from the 30000 long string), it would immediately terminate the application. I don't remember how VS would behave if debugging this but it seems possible it would just go all blank and not show any messages or anything.
So you should at least test this hypothesis by making sure you wrap the entire method in a try-block and add a catch at the end where you break into the debugger and dump the exception to debug output, like this:
try
{
....
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
Debugger.Break();
}
|
|
|
|
|
By the way, your signature uses the bitwise and where a logical and is required - no doubt caused by the fact that & is the character that marks an entity reference in HTML, so that && actually becomes && in source...
|
|
|
|
|
hi
i have one dropdown list and i get the data from the database in
dropdownlist. now i need to select the data from the dropdown list
and after selecting i need to insert that text into the database.
i try ddlproduct.selecteditem.text where ddlproduct is a drodownlist
id but i get the first value from the dropdown if i select some other
value i am getting the first value only
i forget to tell one thing i am using c#
please help me with some code and example
thanks
|
|
|
|
|
I want to know, how can I,
How can i add penel in status bar on design time not with code in window application.
I tried to add columns through property but i couldn't, i did't get any option regarding to penel in property window.
Please do replay.
thanks
modified on Thursday, April 9, 2009 3:43 AM
|
|
|
|
|