Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#4.0
Good day all!!! I wanted to find out if it is possible to create a delegate property. I have something like this (code below):
 
 
        public delegate void SaveDelegate(DataRow data);
        public delegate void UpdateDelegate(DataRow data);
        public SaveDelegate _RowEditorSave = null;
        public UpdateDelegate _RowEditorUpdate = null;
 
        public SaveDelegate RowEditorSave
        {
            get { return _RowEditorSave; }
            set { _RowEditorSave = new SaveDelegate(value); }
        }
 
        public UpdateDelegate RowEditorUpdate
        {
            get { return _RowEditorUpdate; }
            set { _RowEditorUpdate = new UpdateDelegate(value); }
        }
 

//HOW I'M USING IT BELOW
        this.dgvMemberProvider.RowEditorSave = HandlerMemberProvider.Insert;
        this.dgvMemberProvider.RowEditorUpdate = HandlerMemberProvider.Update;
 
 
But I'm getting the following warning:
 
Warning 8 Delegate to an instance method cannot have null 'this'.
 
What am I doing wrong???
Posted 28-Jan-13 5:24am
azinyama1.2K
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Sorry, I don't know how to reproduce the method. You did not show the methods HandlerMemberProvider.Insert and HandlerMemberProvider.Update, and you also never show the invocation of the delegate, and, finally, you did not show the classes/structures where it all is defined. That's the problem.
 
Delegate instances can always be instance methods and pass implicit first parameter this, which is a reference to the instance of the class or structure implementing the handler method.
 
But it looks like you do not understand quite well what you are doing.
 
First of all, SaveDelegate and UpdateDelegate has identical profile. So, you need only one delegate type. Besides, several such types are already predefined as generics in System. So, you can use Action<DataRow> instead. But if you want to define a delegate type for readability, define just one, and don't include the word "Delegate" in it (this is the same as include the work "class" in class name or "application" in the name of executable file):
public delegate void DataUpdater(DataRow data); // something like that
// also consider internal instead of public, is you only use it in the same assembly
 
And then:
class MyClass { // or struct

    //...

    public DataUpdater RowEditorSave { get; set; }
    public DataUpdater RowEditorUpdate { get; set; }
 
    void InvocationDemo(DataRow data) {
        if (RowEditorSave != null) // important!
            RowEditorSave(data);
    }
 
    //...

} //class MyClass
 
I also demonstrated how to correctly invoke the delegate instances: be aware of null.
Again, consider internal instead of public, if you don't use it in a different assembly.
 
For your understanding, this is strictly equivalent to this:
class MyClass { // or struct

    //...

    public DataUpdater RowEditorSave { get { return rowEditorSave; } set { rowEditorSave = value; } }
    public DataUpdater RowEditorUpdate { get { return rowEditorUpdate; } set { rowEditorUpdate = value; } }
  
    DataUpdater rowEditorSave, rowEditorUpdate;
 
    void InvocationDemo(DataRow data) {
        if (rowEditorSave != null) // important!
            rowEditorSave(data);th
    }
 
    //...

} //class MyClass
 
Finally, you should have this or another class/structure to add some handlers to the invocation lists of the delegate instances. You can always have more than one handlers for one delegate instance. You method HandlerMemberProvider.Insert should be some static or instance method, accepting one DataRow parameter (implicit this is a first parameter in case of instance method), and it should return void. In other words, it should match DataUpdater signature.
 
That's all.
 
—SA
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

I just tried it by pasting into one of my classes and cutting out the "junk" that I don't have:
        private void button1_Click(object sender, EventArgs e)
            {
            RowEditorSave = Insert;
            RowEditorUpdate = Update;
            }
 
        public delegate void SaveDelegate(DataRow data);
        public delegate void UpdateDelegate(DataRow data);
        public SaveDelegate _RowEditorSave = null;
        public UpdateDelegate _RowEditorUpdate = null;
        public void Insert(DataRow dt) { }
        public void Update(DataRow dt) { }
        public SaveDelegate RowEditorSave
            {
            get { return _RowEditorSave; }
            set { _RowEditorSave = new SaveDelegate(value); }
            }
 
        public UpdateDelegate RowEditorUpdate
            {
            get { return _RowEditorUpdate; }
            set { _RowEditorUpdate = new UpdateDelegate(value); }
            }
I get no errors, compilation or run time. So...A question.
 
Is this in a Static class?
  Permalink  
Comments
Sergey Alexandrovich Kryukov at 28-Jan-13 11:04am
   
OP could not define a non-static handler in a static class. If a handler is static, it's fine. This is how delegates work. This can be non-null and help to use implementation detail of the class declaring the handler method.
 
I just don't know how to reproduce this weird message. OP must have done something really weird, without showing it to us.
 
—SA
OriginalGriff at 28-Jan-13 11:12am
   
I know - that's why I was confused. But static is the only way I can think of to get any message involving a null this reference - I just can't think of a way to generate it, unless the dgvMemberProvider is static somewhere down the line. I'm clutching at straws! :laugh:
Sergey Alexandrovich Kryukov at 28-Jan-13 11:19am
   
Right. I just say, what you suspect sounds close, but static won't cause this error message. I personally tried all I write about this issue. The use of the delegate property is a trivial issue, by the way.
...I'm just thinking: we are scratching out head, but the code and the error can be something quite trivial and... totally unrelated to what we are discussing.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Thanks for the responses guys. Indeed I'm a bit of a newbie to C#. Took note of all comments and suggestions.
 
Methods insert and update are static:
 
        public static void Update(DataRow Data)
        {
            SetParameterValues(Data);
 
            try
            {
                _SqlDataAdapter.UpdateCommand.Parameters["@Action"].Value = "UPDATE";
                _SqlDataAdapter.UpdateCommand.Parameters["@User_RowID"].Value = GlobalClass.User_RowID;
 
                SqlDatabase.ExecuteSqlDataAdapter(_SqlDataAdapter.UpdateCommand);
 
                if (Convert.ToBoolean(_SqlParameter[5].Value))
                {
                    Data.AcceptChanges();
                }
                else
                {
                    Data.RejectChanges();
                    throw new Exception(Convert.ToString(_SqlParameter[6].Value));
                }
 
                Data.Table.AcceptChanges();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
 
This is how I was invoking:
 
        public void ShowRowEditor(DataRow data)
        {
            firstVisibleCol = this.FirstDisplayedCell.ColumnIndex;
 
            cellRectangle = RectangleToScreen(this.GetCellDisplayRectangle(firstVisibleCol, this.CurrentRow.Index, false));
            cellPoint = this.GetCellDisplayRectangle(firstVisibleCol, this.CurrentRow.Index, false).Location;
            popupPoint = this.PointToScreen(cellPoint);
 
            this.RowEditor = new RowEditorForm();
            this.RowEditor.InitRowEditor(this, data, this.DisableOnUpdate);
            this.RowEditor.Location = new Point(popupPoint.X, popupPoint.Y + ((cellRectangle.Height - 26) / 2));
 
            if (data.RowState == DataRowState.Added)
                this.RowEditor.SaveButtonText = "Save";
            else
                this.RowEditor.SaveButtonText = "Update";
 
            DialogResult result = this.RowEditor.ShowDialog(this);
 
            if (result == DialogResult.OK)
            {
                if (data.RowState == DataRowState.Added)
                {
                    if (this.RowEditorSave == null)
                        return;
 
                    this.RowEditorSave.Invoke(data);
                }
                else
                {
                    if (this.RowEditorUpdate == null)
                        return;
 
                    this.RowEditorUpdate.Invoke(data);
                }
            }
            else if (result == DialogResult.Cancel)
            {
                if (data.RowState == DataRowState.Added)
                {
                    data.Delete();
                }
                else
                {
                    data.RejectChanges();
                }
            }
        }
 
I changed the following (and error/warning is now gone):
 
        //public delegate void SaveDelegate(DataRow data);
        public delegate void DataDelegate(DataRow data);
        //public SaveDelegate _RowEditorSave = null;
        //public UpdateDelegate _RowEditorUpdate = null;

        public DataDelegate RowEditorSave
        {
            get;
            set;
            //get { return _RowEditorSave; }
            //set { _RowEditorSave = new SaveDelegate(value); }
        }
 
        public DataDelegate RowEditorUpdate
        {
            get;
            set;
            //get { return _RowEditorUpdate; }
            //set { _RowEditorUpdate = new UpdateDelegate(value); }
        }
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 George Jonsson 215
1 Kornfeld Eliyahu Peter 169
2 OriginalGriff 120
3 PIEBALDconsult 110
4 BillWoodruff 85
0 OriginalGriff 6,165
1 DamithSL 4,658
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,649
4 Sergey Alexandrovich Kryukov 3,294


Advertise | Privacy | Mobile
Web02 | 2.8.141220.1 | Last Updated 29 Jan 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100