Link to home
Start Free TrialLog in
Avatar of crazy4s
crazy4s

asked on

how to return value from a constructor in c#

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

ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of crazy4s
crazy4s

ASKER

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?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of crazy4s

ASKER

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?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of crazy4s

ASKER

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.
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".
Avatar of crazy4s

ASKER

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?
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.
Avatar of crazy4s

ASKER

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

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
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>?
Avatar of crazy4s

ASKER

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

Hi,

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