|
Marshall Rosenstein wrote: I always though it was better to return a single typed object with queryable properties. That way, if you need more return information, you modify the object, rather than the method signature. It, by definition, makes your code more object-oriented.
Now, if only it was possible to use C# 3.0's anonymouse types for function return values... imagine this:
var foo(string arg1, int arg2, float[] arg3)
{
return new {tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0]};
}
|
|
|
|
|
The problem is that if you were to externally link to a library containing such a function, there's no easy way to determine the properties available from "var" at compile time - Intellisense would certainly fail. Strangely, this compiles fine:
public object foo( string arg1, int arg2, float[] arg3 )
{
return new { tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0] };
}
But again, what is the object? What do you cast it to? Reflection might work in this case, but that seems kind of clunky to me.
Actually, something like this might actually work:
public var MyDynamicClass foo( string arg1, int arg2, float[] arg3 )
{
return new var{ tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0] };
}
In this case, MyDynamicClass becomes what I might call a "dynamic type", but it can still be inferred by the compiler and its meta-data made available externally as if it were a formally defined class. But there are all sorts of problems this would induce in terms of maintenance and version compatibility.
Or how about something like this:
public var foo( string arg1, int arg2, float[] arg3 )
{
return new var("MyDynamicClassName"){ tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0] };
}
---------------------
Marshall Rosenstein
.NET Consultant
modified on Wednesday, December 19, 2007 9:38:04 AM
|
|
|
|
|
Thinking too generically?
Return values of type object are common enough.* I don't see any problem with that approach. It's also a mechanism for circumventing the inability to create a single method w/a variable arg list. (Overloads really don't come close to replacing this joy of C ).
At first, I was thinking about strategies to pass in the type of the class that was to be returned, and since this was passed in by the caller its type was known by the caller. The typeid could be used, an object of that type created, and cast to a generic object type for return.
All this to avoid simply returning a struct containing the appropriate info (?).**
Then I got to thinking about the whole thing. In what circumstance could I get any real added-value functionality by returning an arbitrary type? Here's what I was thinking: the full generalization is to submit arbitrary data and return an arbitrary type. How do we process the former without making so large and complex a logic tree that it's unworkable? The crux of this is that it implies a totally generic data-processor (i.e., it too is a sort of arbitrary).
All things wonderful could be accomplished by either returning (a) structure, or (b) an object container (like ArrayList), or (c) an generic object.
The methods utlimately need some sort of body to do anything and so if we make it too abstract we end up with either too much or nothing at all
* Example: SqlClient::SqlCommand::ExecuteScaler()
** Time/watch analogy in a different area of the main thread
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
|
|
|
|
|
When you call ExecuteScaler(), the result can be cast to a known value type. The problem with returning an object in the var case (C# 3.0) is that you are returning an anonymous type. So what type do you cast the object to get at its data / properties after calling the function? To cast it to something useful, the definition of the type has to be publically available to the caller somewhere. Otherwise, you're left with using reflection on the object.
I think the point of an anonymous type is to allow the return of arbitrary data without vastly increasing the number of types predefined in the namespace. The common usage of a struct requires the data to conform to a structure, rather than having a structure conform to the data (as is the case with anonymous types).
In LINQ, even if the input data is not arbitrary, the data that gets returned from a query can be abitrary due to the many possible transformations.
---------------------
Marshall Rosenstein
.NET Consultant
|
|
|
|
|
The point that struck home to me is that, in general, I create an function to do a specific job, which requires specific data, and allows specific processing.
As a mental exercise, what you're saying is fine. I just (accidentally) gave it some practical thought. An arbitrary return type would imply arbitrary arguments (ok - pass in an Obj) and arbitrary processing - the anything function - that's got me beat.
On the other hand, if any of the these are fixed, than so to would be the possible return types. The type could declared without bothering to allocate its dat (for example), be passed in as the first value of the arbitrary data list. Since the processing possibilities in a real system are limited, it could be type-id'ed, processed accordingly into that type, and then cast as an generic object for the return. TYpe-id it again on the other side, or cast it directly upon return.
In real life, I've usually worked this out as either structures or ArrayLists as return types.
This stuff may work differently for me (in C++) than it does in C#.
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
|
|
|
|
|
I think I understand what you are saying. But at a pragmatic level, I'm suspicious that the language feature of anonymous types was added just to support Intellisense for lazy programmers like myself.
---------------------
Marshall Rosenstein
.NET Consultant
|
|
|
|
|
Balboos wrote: variable arg list
params object[] doesn't work for you?
|
|
|
|
|
Marshall Rosenstein wrote: The problem is that if you were to externally link to a library containing such a function, there's no easy way to determine the properties available from "var" at compile time - Intellisense would certainly fail.
I'd say you're wrong about that. Why? var isn't a Variant-like type from VB6 days. The Type of var is determined at compile-time. When you write
new { tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0] }; <big>
</big>
a new type is generated (named something like "Anonymous1" or equivalent). So, technically, it is not hard to implemented the feature I proposed; except maybe it would be slow/painful to add support for it in the IntelliSense tool, though doesnt seem too hard - since they can do it for variables, why not for functions. IMO they did not see it as a needed feature. Perhaps VS2010
Marshall Rosenstein wrote: Strangely, this compiles fine:
public object foo( string arg1, int arg2, float[] arg3 )
{
return new { tmp=arg1+"test", md=arg2 % 42, len=arg3.Length, first=arg3[0] };
}
Of course. as said before, the new {...} statement makes the compiler generate a new class, and the "new" makes an instance of it. And then returning it, well, it boxes it into the object, and that's it.
Hmm, I just might post this on Connect. Maybe they'll add this. Any idea on where the Connect website is? :p
|
|
|
|
|
Hi,
I haven't heard of the Connect website -- is it something I should explore?
I don't think they'll ever add var as a return function value, and here's why.
The Type of var is known at compile time since it is the compiler that auto-generates the Type. However, the accessibility of the Type is always internal sealed . Also, if you look at the IL for foo() , there is no boxing that occurs, since anonymous types are not value types.
Since public var foo() is public , it would require that the return Type of foo() to be public as well. This is especially important when the method you are calling is in an external library. Otherwise you introduce the following problems:
- The
var or object can't be cast to its original type by the caller. - You can only access the data in the
var using reflection. - Since the return Type of
foo() isn't named in the meta-data (this can be verified using reflection), the Intellisense parser would have to both parse and interpret the IL of the third party library function to determine the actual return Type. In some cases, it is not possible to determine the return Type at compile time. For example, if the function logic contained a switch statement where what is returned is conditioned in some way by the runtime values of the input parameters:
public var foo()( int myRuntimeVal )
{
switch( myRuntimeVal ){
case 1: return new{ Value=1 };
default: return new{ Name="Hello", Value="World" };
}
} - Once the IL analysis successfully determined the Type, it would have to use reflection to determine the available properties of the Type.
Changing the auto-generated type from internal to public is in essence the same as proposing that anonymous types no longer be anonymous. Even so, on another post, I proposed a couple ways this might be done. "Named auto-generated types" is of course possible. This is adding language support to create a public contract based on ad-hoc definitions of data-structures. In practice, these definitions are subject to change due to the context in which such definitions are intended to be used - data queries. This becomes a real maintenance problem in terms of "published" interfaces, especially for third-party users.
One easy solution would be to only allow the var keyword to be used for private or internal functions.
---------------------
Marshall Rosenstein
.NET Consultant
modified on Thursday, December 20, 2007 12:23:31 PM
|
|
|
|
|
Marshall Rosenstein wrote: I haven't heard of the Connect website -- is it something I should explore?
MS' feedback site. http://connect.microsoft.com/[^]
Marshall Rosenstein wrote: I don't think they'll ever add var as a return function value, and here's why.
The Type of var is known at compile time since it is the compiler that auto-generates the Type. However, the accessibility of the Type is always internal sealed. Also, if you look at the IL for foo(), there is no boxing that occurs, since anonymous types are not value types.
Since public var foo() is public, it would require that the return Type of foo() to be public as well. This is especially important when the method you are calling is in an external library. Otherwise you introduce the following problems:
Hmm, very valid point. However, why not make anonymous types public sealed ? I don't see any major problems with this.
Marshall Rosenstein wrote: Since the return Type of foo() isn't named in the meta-data (this can be verified using reflection), the Intellisense parser would have to both parse and interpret the IL of the third party library function to determine the actual return Type. In some cases, it is not possible to determine the return Type at compile time. For example, if the function logic contained a switch statement where what is returned is conditioned in some way by the runtime values of the input parameters:
//Return Type cannot be determined at compile time
public var foo()( int myRuntimeVal )
{
switch( myRuntimeVal ){
case 1: return new{ Value=1 }; //Anonymous Type 1
default: return new{ Name="Hello", Value="World" }; //Anonymous Type 2
}
}
That, IMHO, shouldn't be allowed at all. After all, its like saying
public CType1 foo(int myRuntimeVal)
{
switch(myRuntimeVal){
case 1: return new CType1(1);
default: return new CType2("Hello", "World");
}
} assuming CType1 and CType2 exist as actual classes, are accessible, and have the needed constructors, of course.
I do have to agree with the "Named auto-generated types" idea, however.
|
|
|
|
|
Or SQRT ( 4 ) returns { 2 , -2 }
|
|
|
|
|
Can't wait to make recursive calls on this one:
SQRT(SQRT(SQRT(SQRT(4)))) = { ... };
|
|
|
|
|
That function will probably just use the first return. You normally have a special way of dealing with multiple return values.
Example (Scheme):
(define (mv) (values 1 2))
(call-with-values mv +) => 3
xacc.ideIronScheme a R5RS/R6RS-compliant Scheme on the DLR
The rule of three: "The first time you notice something that might repeat, don't generalize it. The second time the situation occurs, develop in a similar fashion -- possibly even copy/paste -- but don't generalize yet. On the third time, look to generalize the approach."
|
|
|
|
|
Xiangyang Liu wrote: it will return { True, False, NotSure, WhateverAnswerYouWant }
No, not an enumerated value, actually two or more values; like MatLab
(x,y) = getXandYvalues();
A good language allows a programmer to *quickly* convert the ideas in their mind to simple, easy to understand language constructs (lines of code), while enforcing enough "discipline" to keep the programmer out of trouble. Yes, a programmer can always go declare a struct or class to return multiple values, but I have found over the years that this is a real roadblock to creative thinking. I have to stop what I'm doing, go find a good place in the code to declare the new struct (give it the proper scope), think of a good descriptive name for it (and make sure it doesn't clash), worry about "what happens if someone uses this for...", i.e. I have to start building constructors and destructors, etc. All in all, by the time I'm finished with the struct to return more than one value, I've forgotten why I wanted it in the first place!
To paraphrase an old adage; I just wanted to know what time it was, but the language forced me to build a watch!
David
---------
Empirical studies indicate that 20% of the people drink 80% of the beer. With C++ developers, the rule is that 80% of the developers understand at most 20% of the language. It is not the same 20% for different people, so don't count on them to understand each other's code.
http://yosefk.com/c++fqa/picture.html#fqa-6.6
---------
|
|
|
|
|
Xiangyang Liu wrote: IsUserLoggedOn which returns True or False
Or
{ True , ::LoginTime:: , ::Workstation:: , ::SnackPreference:: , ::CoffeeIsGettingLow , ::PleaseSendMasseuse:: , 42 }
|
|
|
|
|
I personally would also like to have a good IDE too to support such a language.
Nibu thomas
Microsoft MVP for VC++
Code must be written to be read, not by the compiler, but by another human being.
Programming Blog: http:\\nibuthomas.wordpress.com
modified on Tuesday, December 18, 2007 4:32:43 AM
|
|
|
|
|
Nibu babu thomas wrote: good IDE too to support such a language
Not necessarily. As a matter of fact, sometimes IDE makes people lazy to think out of the box. At least with respect to the career arena of Chennai, if you pick up a handful of them and ask a few questions like the following:
1) How to refer a Web Service in C# application?
You may end up getting weird responses like 'Right Click -> Add Web Reference' instead of 'using WSDL.exe'.
Nevertheless IDE makes a rapid development effort cutting short of the time required for the development but I would say at least for beginners, there should be a restriction on IDE and more emphasis on use of the various tools that ship with the framework etc. What do you say?
Vasudevan Deepak Kumar
Personal Homepage Tech Gossips
A pessimist sees only the dark side of the clouds, and mopes; a philosopher sees both sides, and shrugs; an optimist doesn't see the clouds at all - he's walking on them. --Leonard Louis Levinson
|
|
|
|
|
Vasudevan Deepak K wrote: What do you say?
For beginners this could be an option, but when advanced development comes in we need to have an IDE.
Well I started learning .Net by typing code in a notepad but that was just for adding two numbers, displaying prime numbers(just for getting a hold of things) and then moved on to VS, so yes it helps to know how things work behind the scenes.
Nibu thomas
Microsoft MVP for VC++
Code must be written to be read, not by the compiler, but by another human being.
Programming Blog: http:\\nibuthomas.wordpress.com
|
|
|
|
|
Nibu babu thomas wrote: advanced development comes in we need to have an IDE.
Could you explain more please? I know some pretty serious developer who use nothing but vi and the command-line.
regards,
Paul Watson
Ireland & South Africa
Andy Brummer wrote: Watson's law:
As an online discussion of cars grows longer, the probability of a comparison involving the Bugatti Veyron approaches one.
|
|
|
|
|
Paul Watson wrote: Could you explain more please? I know some pretty serious developer who use nothing but vi and the command-line.
Well advanced development means the scale of the project, for small scale projects it's ok maybe not to have an IDE.
VS is a quite helpful to me in the sense that it provides some real nice features which supports development in VC++. For eg: resource editor, source browsing, project dependencies, intellisense, some shortcuts for indentation, matching braces, debugging etc.
As you said there are side effects too if asked to work in a project without intellisense I will take some time to get used to it, though I try not to use it too much but time is a problem.
But the bottomline is that these are tools to help us in development and to save time.
Nibu thomas
Microsoft MVP for VC++
Code must be written to be read, not by the compiler, but by another human being.
Programming Blog: http:\\nibuthomas.wordpress.com
|
|
|
|
|
Fair enough but I think "need to have an IDE" is too strong a phrase. Nobody needs an IDE. It is a helpful tool at times but no project and no programmer should be dependent on one.
I still do know programmers who work on large projects with just vi and a command line. They have command line tools that allow them to work very quickly.
I am not at their level but I work on reasonably sized projects using a text-editor and the command line. I find IDE UIs to be slow, buggy and often distracting. Using the command line tools provided by the framework and the OS is proving to be sufficient. A few terminal windows open and you have all the multi-tasking tools you need.
(Just to reiterate: I used VS for a good many years and went through the "IDEs rock!" phase too. I've swung the other way now and will probably swing back a bit into a mid-stream position in a few years. They are useful tools but not absolutely required.)
regards,
Paul Watson
Ireland & South Africa
Andy Brummer wrote: Watson's law:
As an online discussion of cars grows longer, the probability of a comparison involving the Bugatti Veyron approaches one.
|
|
|
|
|
Paul Watson wrote: Fair enough but I think "need to have an IDE" is too strong a phrase. Nobody needs an IDE. It is a helpful tool at times but no project and no programmer should be dependent on one.
Well the reason being that I am quite addicted to VS(currently using VC6). I personally also like that all required files be open in one parent window and I can move between these windows easily. Also some pretty nifty features like last opened files, projects, macros which saves time and helps too.
I agree to what you said that everybody doesn't need to have an IDE for development(quite a blanket statement from my part).
I remember writing programs in vi and then going back to command line to compile, link, debug. I was not comfortable, but got used to it, but quickly moved back to VS.
But don't agree to IDE UI's being slow, VC6 UI is fast enough for me. I've got about 44 sub projects, at a time about 15 to 20 sub windows open, and it works well for me.
Nibu thomas
Microsoft MVP for VC++
Code must be written to be read, not by the compiler, but by another human being.
Programming Blog: http:\\nibuthomas.wordpress.com
|
|
|
|
|
Nibu babu thomas wrote: I personally also like that all required files be open in one parent window and I can move between these windows easily. Also some pretty nifty features like last opened files, projects, macros
Oh absolutely, I use TextMate which isn't an IDE but does offer those bits. I couldn't go all the way and use stripped down vi.
I found in my waning days of VS usage I used it mainly as a text editor. I avoided all the built-in framework helpers, the designers and on-the-fly checkers etc. Once I got to that point I realised a faster, cleaner text editor would do as well.
regards,
Paul Watson
Ireland & South Africa
Andy Brummer wrote: Watson's law:
As an online discussion of cars grows longer, the probability of a comparison involving the Bugatti Veyron approaches one.
|
|
|
|
|
Nibu babu thomas wrote: I personally would also like to have a good IDE too to support such a language.
Ever since moving away from .NET and Visual Studio to Ruby and a text-editor I have come to realise the evils of IDEs.
You become so dependant on the IDE. It is a useful tool to have around but it is good to be able to code, compile, deploy, debug etc. without one.
regards,
Paul Watson
Ireland & South Africa
Andy Brummer wrote: Watson's law:
As an online discussion of cars grows longer, the probability of a comparison involving the Bugatti Veyron approaches one.
|
|
|
|
|
Paul Watson wrote: It is a useful tool to have around but it is good to be able to code, compile, deploy, debug etc. without one.
Without doubt. This is a definitive requirement at least when the product is going for release and we can not expect Visual Studio in client systems.
Vasudevan Deepak Kumar
Personal Homepage Tech Gossips
A pessimist sees only the dark side of the clouds, and mopes; a philosopher sees both sides, and shrugs; an optimist doesn't see the clouds at all - he's walking on them. --Leonard Louis Levinson
|
|
|
|
|