简体   繁体   中英

Why is this c# constructor not working as expected?

I am trying to initialize a constructor differently if it's called with a parameter that meets certain criteria and I have the following code.

class MessageEventArgs : EventArgs
{
    private int _pId;
    private string _message;
    private string _channelPath;

    public MessageEventArgs(string message)
    {
        _pId = Process.GetCurrentProcess().Id;
        _message = message;
        _channelPath = null;
    }

    public MessageEventArgs(string[] details)
    {
        if (details.Length == 1)
        {
            new MessageEventArgs(details[0]);
            return;
        }
        _pId = int.Parse(details[0]);
        _message = details[1];
        _channelPath = details[2];
    }
}

Which surprisingly is not working, on debugging and stepping through line by line, I see everything called properly, but after instantiation, pId and _message have their default values ie 0 and null

You are not invoking the other constructor, you are creating a second instance which you initialize with the default values.

Hence the first instance is still uninitialized.

You need to do it like this:

class MessageEventArgs : EventArgs
{
    private int _pId;
    private string _message;
    private string _channelPath;

    public MessageEventArgs(string message)
    {
        _pId = Process.GetCurrentProcess().Id;
        _message = message;
        _channelPath = null;
    }

    public MessageEventArgs(string[] details)
    {
        if (details.Length == 1)
        {
            _pId = Process.GetCurrentProcess().Id;
            _message = details[0];
            _channelPath = null;
            return;
        }
        _pId = int.Parse(details[0]);
        _message = details[1];
        _channelPath = details[2];
    }
}

I would probably check if the details are null also..

As per spec, in C#, you cannot call another constructor from a class. So it's not the return statement, but it's the improper attempt to call the other constructor. You have to make an Initialize method that embodies what you're trying to do and call it from both methods.

class MessageEventArgs : EventArgs
{
    private int _pId;
    private string _message;
    private string _channelPath;

    public MessageEventArgs(string message)
    {
        Initialize( message );
    }

    public MessageEventArgs(string[] details)
    {
        if (details.Length == 1)
        {
            Initialize( details[ 0 ] );
            return;
        }

        _pId = int.Parse(details[0]);
        _message = details[1];
        _channelPath = details[2];
    }

    private void Initialize(string message)
    {
        _pId = Process.GetCurrentProcess().Id;
        _message = message;
        _channelPath = null;     
    }
}

Not sure this is any cleaner but you could try the following:

    public MessageEventArgs(string message)
        : this(new [] {message})
    {
    }

    public MessageEventArgs(string[] details)
    {
        if (details.Length == 1)
        {
            _pId = Process.GetCurrentProcess().Id;
            _message = details[0];
            _channelPath = null;
        }
        else
        {
            _pId = int.Parse(details[0]);
            _message = details[1];
            _channelPath = details[2];
        }
    }

You can't return anything from a constructor. Try something like this.

    if (details.Length == 1)
    {
        _pId = Process.GetCurrentProcess().Id;
         _message = message;
        _channelPath = null;
    }
    else 
    {
        _pId = int.Parse(details[0]);
        _message = details[1];
        _channelPath = details[2];
    }

You can't call a constructor of the same class from a constructor. Your code creates a local instance of MessageEventArgs, and it goes out of scope which is why you don't see the expected behavior.

Constructors are meant to create the instance of the object based on the parameters passed. Overloading is meant to allow different parameters to be passed and result in proper instantiation of the object. Constructors are meant to be atomic so that if you remove one constructor it does not impact the others.

Your code should look like this:

class MessageEventArgs : EventArgs
{
    private int _pId;
    private string _message;
    private string _channelPath;

    public MessageEventArgs(string message)
    {
        _pId = Process.GetCurrentProcess().Id;
        _message = message;
        _channelPath = null;
    }

    public MessageEventArgs(string[] details)
    {
        if (details.Length == 1)
        {
            _pId = Process.GetCurrentProcess().Id;
            _message = details[0];
            _channelPath = null;
        }
        else 
        {
            _pId = int.Parse(details[0]);
            _message = details[1];
            _channelPath = details[2];
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM