Solved

how to return value from a constructor in c#

Posted on 2012-03-23
15
562 Views
Last Modified: 2013-12-16
Hi all,
Since is a constructor i'm not sure how can i return a value?
i have this code (see below), and i would like to have a return value back to the parser.cs (line 17 in Parser code).
Can anyone show me how should i do this?

public class VariableDecl : Declaration
    {
        Variable v = null;
        Type t = null;

        public VariableDecl(List<Declaration> Declarations)
            : base(Declarations)
        {

        }

        public VariableDecl(Variable v1, Type t1)
            : base()
        {
            v = v1;
            t = t1;
            toString(); <-- i need to return this value back to Parser.cs
        }

        public new String toString()
        {
            return toStringIndented("");
        }

        public new String toStringIndented(String indent)
        {
            Console.WriteLine("Variable Declaration: " + v.toString() + " " + t.toString());
            return indent + "Variable Declaration: " + v.toString() + " " + t.toString();
        }
    }

Open in new window


Parser.cs
private List<Declaration> declaration()
        {
            List<Declaration> result = new List<Declaration>();
            Type t = type();
            Variable v = new Variable(match(Token.TokenType.Identifier));

            if (current_token.getType() == Token.TokenType.LeftBracket)
            {
                match(Token.TokenType.LeftBracket);
                int i = Convert.ToInt32(match(Token.TokenType.IntLiteral));
                match(Token.TokenType.RightBracket);
                ArrayDecl ad = new ArrayDecl(v, t, i);
                result.Add(ad);
            }
            else
            {
                VariableDecl vd = new VariableDecl(v, t); <-- vd should get the return value from the above code (VariableDecl)
                result.Add(vd);
            }

            while (current_token.getType() == Token.TokenType.Comma)
            {
                match(Token.TokenType.Comma);
                Variable v1 = new Variable(match(Token.TokenType.Identifier));
                if (current_token.getType() == Token.TokenType.LeftBracket)
                {
                    match(Token.TokenType.LeftBracket);
                    int i = Convert.ToInt32(match(Token.TokenType.IntLiteral));
                    match(Token.TokenType.RightBracket);
                    ArrayDecl ad = new ArrayDecl(v1, t, i);
                    result.Add(ad);
                }
                else
                {
                    VariableDecl vd2 = new VariableDecl(v1, t);
                    result.Add(vd2);
                }
            }

            match(Token.TokenType.Semicolon);

            return result;
        }

Open in new window

0
Comment
Question by:crazy4s
15 Comments
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
The short answer is:  you can't. A constructor is meant to initialize an objects member fields/properties. It does not return data. This is the reason you don't put a return type in the constructor's signature. If you want to return something from your class, expose a public property or method which returns the appropriate value and call that from the external entity.
0
 

Author Comment

by:crazy4s
Comment Utility
hmmm so do you meant that i've to create a new method lk toStringIndented passing the 2 variables v and t?
or do i have a better way to solve this?
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
Comment Utility
Please don't take this as me being rude, but I think you need to spend some time brushing up on Object Oriented programming. I say this not only because of some things I've seen here, but also what I have seen in some other questions. There are just some things you are doing, and trying to do, which seem like you might be making it harder than it needs to be. You might start here.

That said, I am more than happy to help with your current issue  = )

******************************

Going back to your code, specifically this comment--"vd should get the return value from the above code (VariableDecl)"--you have to understand that in effect vd does have the return value of the thing on the right of the = sign. Now that's a bit contradictory to what I said earlier, but I didn't want to confuse you off the bat.

When you say "Something x = new Something", x is going to be a reference to the object that new created in memory. The type of that object (and almost always of x) is going to be Something. (Please don't confuse my use of the term "Something" as in "Hey, grab me something from the fridge. I am speaking of a specific thing; in this case, that "thing" just happens to be named Something.) When you call new, you are allocating space in memory, and the constructor associated with the type you denoted will fill that new space in memory with whatever values it (the constructor) is designated to populate that space with.

So why can't the constructor perform some operation and return you a result? Well, the constructor can perform some operation, but it's job is to initialize the new instance of an object that was created in memory by new. If you want to return the sum of two numbers, the boolean result of some function, another, new instance of some object (even of the same type as the class itself), or any other type of data, then you have to create either public properties or methods which return the data. Your constructor can calculate the sum, call the function as store the boolean result, instantiate a new instance of some object, or acquire any other type of data, but it cannot return it anywhere. It can only store it in the member fields (variables, generally private variables) for some other property or method of the same class to return to a caller (the thing that "calls" the property or method from [generally] outside of the class).

For your current issue, I would say "yes", create a new method which returns the value you are interested in. Honestly, I am not sure what the code you commented is intended to do. You create a new instance of VariableDecl, and then you add it to the member List<VariableDecl>. I'm not sure where the "return value" comes into play in those two lines of code. Perhaps you can elaborate.
0
 

Author Comment

by:crazy4s
Comment Utility
i'm actually creating an abstract syntax tree program... variabledecl is a subclass of Declaration...
so each variabledecl(the return value will be a type and an identifier in my case) will be added to the list of Declaration which i have (List<Declaration>) and then at last print out the list...
hope you don't mind me asking lots of questions because i'm new to c# and especially using the list<> method so i'm trying hard to figure out by asking well kind of lot questions on this topic but none of them seems to solve my prob and some even not replying anymore, and so i'm stuck to where they told me to be...

okay so now what should i do is in my parser i should pass the args to the variabledecl method instead of the constructor ryte? so does it meant that my constructor will be doing nothing?
0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
Comment Utility
hope you don't mind me asking lots of questions
Why would I mind? The whole point of EE is to ask (and answer) questions  ; )

so does it meant that my constructor will be doing nothing?
It is perfectly plausible for a constructor to do nothing. There is no rule that says your constructor must do something in order to be meaningful. You just need to make sure that your object is properly initialized. NullReferenceException is probably the single biggest exception that is encountered in everyday programming. The most likely culprit of that exception:  improperly initialized variables.

You made the method toString public. Why not call it where you expect the value to be returned outside of the class? In other words:

In VariableDecl Class
...

public VariableDecl(Variable v1, Type t1)
            : base()
{
    v = v1;
    t = t1;
    // Remove this next line
    // toString(); <-- i need to return this value back to Parser.cs
}

...

Open in new window


In Parser.cs
...

else
{
    VariableDecl vd = new VariableDecl(v, t); <-- vd should get the return value from the above code (VariableDecl)
    vd.toString();
    result.Add(vd);
}

...

Open in new window

0
 

Author Comment

by:crazy4s
Comment Utility
in this case does the vd in result.Add(vd); is the return value from toStringIndented()? because when i try to print the list of result(which is the list<declaration>) it prints out AbstractSyntax.VariableDecl instead of the actual return value, but when i add a print statement for vd.toString() (before result.Add(vd), it did prints out the value. so how does this works actually, i'm a little confused with it.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
You defined the method toString to both print a string to the Console window and return a string from the function call. I didn't capture the return value from the function because I was focused on the fact that you have that method writing to the Console. Allow me to amend my previous snippet:

...

else
{
    VariableDecl vd = new VariableDecl(v, t); <-- vd should get the return value from the above code (VariableDecl)
    string result = vd.toString();
    result.Add(vd);
}

...

Open in new window


Now you would have the result of toString stored in the variable "result".
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:crazy4s
Comment Utility
hmmm that's just a print statement to make sure it actually pass the result that i want...
but at the beginning of this method i actually have (line 3 at Parser.cs - the top post)
List<Declaration> result = new List<Declaration>();

so i'm actually adding the return value into the result list so i can't redeclared list as string in this case ryte?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
Let's clarify a couple things:  a "return value" is something that is returned by a function call. Also, a constructor (for our purposes) is not a function, so you don't have anything returned. The language construct that is doing the returning when you create a new object is the new keyword. A function returns some value; the new keyword returns a reference to some newly allocated object. (It's a tad confusing, I know, but you have to make the distinction so you know what your code is doing.)

In your else clause, you don't have any "return values". You have a reference to a newly-create object (that was returned by new). You are adding the object this reference points to to your List<Declaration>. No cannot redeclare the List<Declaration> as a String because those types would not match, and you would receive a compiler error. However, even though you added the object to your List<Declaration>, you still have a reference to the object that was created. This is the variable "vd". Since you have a reference to an object (which is properly instantiated), you can call methods of the class against it. This is what I did in line 6 of my last post. If you need to do something else with the string that "result" holds after that line executes, then you can pass that string to the appropriate function, or you can store it to some other variable. It all depends on your intent for that string.
0
 

Author Comment

by:crazy4s
Comment Utility
okay so if i want to add this string (in my case returning line 4) into result (a list<>) how should i do it? because when i try to do result.Add(some string) it doesn't allow me to do so.
 public new String toStringIndented(String indent)
        {
            Console.WriteLine("Variable Declaration: " + v.toString() + " " + t.toString());
            return indent + "Variable Declaration: " + v.toString() + " " + t.toString();
        }

Open in new window

0
 
LVL 4

Expert Comment

by:kdebugs
Comment Utility
Hi Krazy4s,

I'm no expert in c#, but I have a feeling that you're having problems due to the sequence of events taking place when your class is instantiated isn't exactly what you expect. I've had similar problems in vfp in the past, hence my hunch.

Don't know if it's at all possible, but if you put a breakpoint at the very begining of your constructor's code, you should be able to manually check which properties, variables, etc. are accessible to it and which aren't. Then you can adjust your approach accordingly.

Kaufmed is absolutely right; constructors aren't supposed to return values. At best they might return true or false depending on their success or failure instantiating the object. If you are in a situation dealing with "shades of gray" (i.e. "object instantiated but some things missing"), you use a public property or field (probably easier for such a simple need) and that's what the code that instantiated the object should look at.

And yes, please ask as much as you can; this is how we all learn.

alex
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
because when i try to do result.Add(some string) it doesn't allow me to do so.
That is correct. You cannot add a string to your List<Declaration> because a string is not equivalent to a Declaration (i.e. those are two completely different types). What is the intent of the List<Declaration>?
0
 

Author Comment

by:crazy4s
Comment Utility
to keep a list of declarations, let's say if i have a test file smt like this:

line 1: int i, x[10], y, w[100];
in declarations an int is found, so it'll proceed to declaration to check. so this one will actually add type int and identifier i into list<Declaration> result, since i have a comma, so it'll continue and add type int and array name of x with the size 10 into result and so on. And then back to declarations method (this is in parser.cs private List<Declaration> declaration() )

line 2: char name, a[5];
and then List<Declaration> declarations will check again, this time found a char, so proceed to declaration method and do the same thing as above.

parser.cs
private List<Declaration> declarations()
        {
            List<Declaration> ds = new List<Declaration>();
            List<Declaration> dsl = new List<Declaration>();
            while (current_token.getType() == Token.TokenType.Int ||
                current_token.getType() == Token.TokenType.Float ||
                current_token.getType() == Token.TokenType.Char ||
                current_token.getType() == Token.TokenType.Bool)
            {
                dsl = declaration();
                ds.AddRange(dsl);
            }
            return ds; 
        }

        private List<Declaration> declaration()
        {
            List<Declaration> result = new List<Declaration>();
            Type t = type();
            Variable v = new Variable(match(Token.TokenType.Identifier));

            if (current_token.getType() == Token.TokenType.LeftBracket)
            {
                match(Token.TokenType.LeftBracket);
                int i = Convert.ToInt32(match(Token.TokenType.IntLiteral));
                match(Token.TokenType.RightBracket);
                ArrayDecl ad = new ArrayDecl(v, t, i);
                ad.toString();
                result.Add(ad);
            }
            else
            {
                VariableDecl vd = new VariableDecl(v, t);
                vd.toString();
                result.Add(vd);
            }

            while (current_token.getType() == Token.TokenType.Comma)
            {
                match(Token.TokenType.Comma);
                Variable v1 = new Variable(match(Token.TokenType.Identifier));
                if (current_token.getType() == Token.TokenType.LeftBracket)
                {
                    match(Token.TokenType.LeftBracket);
                    int i = Convert.ToInt32(match(Token.TokenType.IntLiteral));
                    match(Token.TokenType.RightBracket);
                    ArrayDecl ad = new ArrayDecl(v1, t, i);
                    ad.toString();
                    result.Add(ad);
                }
                else
                {
                    VariableDecl vd2 = new VariableDecl(v1, t);
                    vd2.toString();
                    result.Add(vd2);
                }
            }

            match(Token.TokenType.Semicolon);

            return result;
        }

Open in new window

0
 
LVL 16

Expert Comment

by:SriVaddadi
Comment Utility
Hi,

May I know what is the original problem you are trying to solve? I mean what is it you are trying to implement?
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now