0

I have an issue where the compiler doesn't appear be be seeing the interface class correctly. I have a base class, called Ctrl, and a number of derived classes, Ctrl_BUTTON, Ctrl_CHECKBOX, etc. Some but not all of them need to have a Font property, so that I can test easily at runtime as to whether the class supports a Font property. Hence I have an interface class, ICtrl_Font. However, I'm getting the designtime error:

'AppData.Ctrl_CHECKBOX' does not contain a definition for 'Font' and no extension method 'Font' accepting a first argument of type 'AppData.Ctrl_CHECKBOX' could be found (are you missing a using directive or an assembly reference?)

The code structure I have.

class ICtrl_Font:

namespace AppData
{
    public interface ICtrl_Font
    {
        Font Font { get; set; }
    }
}

Ctrl_CHECKBOX uses ICtrl_Font thus (I've chopped out irrelevant code for clarity):

namespace AppData
{
    public class Ctrl_CHECKBOX : Ctrl, ICtrl_Font
    {
        private Font _font = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular, GraphicsUnit.Point);

        public override Ctrl Clone()
        {
            Ctrl_CHECKBOX oCopy;

            try
            {
                oCopy = new Ctrl_CHECKBOX(base.Globals, base.Server, base.App, base.Frm);
                if (!base.Copy(oCopy)) throw new Exception(string.Format("Could not clone Ctrl class for {0} copy.", base.CtrlTypeCode));
                oCopy.DesignTimeValue = _designTimeValue;
                oCopy.Enabled = (_enabled.GetType() == typeof(Expression)) ? ((Expression)_enabled).Clone() : _enabled;
                oCopy.Font = new Font(_font.Name, _font.Size, _font.Style, GraphicsUnit.Point);
                oCopy.Text = (_text.GetType() == typeof(Expression)) ? ((Expression)_text).Clone() : _text;
                oCopy.Value = (_value.GetType() == typeof(Expression)) ? ((Expression)_value).Clone() : _value;
                return (Ctrl)oCopy;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        Font ICtrl_Font.Font
        {
            get { return _font; }
            set
            {
                _font = value;
                Console.WriteLine("CHECKBOX: Font.Name -> " + _font.Name);
                base.OnPropertyValueChanged(this, new AppData.PropertyValueChangeEventArgs(this, "Font"));
            }
        }
    }
}

I'm getting the error from within Ctrl_CHECKBOX in the Clone method at the line oCopy.Font = ... but also elsewhere in the code where the Ctrl_CHECKBOX.Font is referenced.

How do I resolve this? Thanks.

Mark Roworth
  • 409
  • 2
  • 15
  • Where are you seeing the error you've posted about? – ProgrammingLlama Feb 28 '22 at 10:38
  • You have explicitly implemented the interface - don't do that if you don't want it only accessible from the interface reference. ie/ `Font ICtrl_Font.Font{ ... }` should be `public Font Font{ ... }` – Jamiec Feb 28 '22 at 10:39
  • Why have you chosen explicit interface implementation for `Font`? That means you can *only* access the `Font` property via a variable/expression of type `ICtrl_Font`. – Damien_The_Unbeliever Feb 28 '22 at 10:39
  • @Llama, as stated at the bottom of the question, "I'm getting the error from within Ctrl_CHECKBOX in the Clone method at the line oCopy.Font = ... but also elsewhere in the code where the Ctrl_CHECKBOX.Font is referenced." – Mark Roworth Feb 28 '22 at 10:42
  • Hi @Damien_The_Unbeliever, I think that's what I want. I have other types of Ctrl, e.g. Ctrl_IMAGEBOX which doesn't have a Font property. When responding to events relating to one of the derived classes of Ctrl, I don't want to have to provide code for each subclass of Ctrl, rather perform the test ```if (typeof(ICtrl_Font).IsAssignableFrom(oCtrl.GetType()))``` and then ```ICtrl_Font oCtrlFont = (ICtrl_Font)oCtrl;``` and then use the ```Font``` property of ```oCtrlFont``` directly. Otherwise I end up with a switch statement with identical code repeated for sub-class. – Mark Roworth Feb 28 '22 at 10:48
  • Explicit interface implementation is, as I said, that you can *only* access the property from an `ICtrl_Font` variable/expression. Implicit interface implementation would *also* allow you to access it, say, via a `Ctrl_CHECKBOX` variable/expression - which is what you're trying to work with in your `Clone` method. You could cast `oCopy` to `ICtrl_Font` but I'm trying to work out why you went in this particular direction in the first place. – Damien_The_Unbeliever Feb 28 '22 at 10:51
  • @Damien_The_Unbeliever - gotcha. Thanks for the additional clarity. Really, I'm going that way for the reason I have stated above. The are some sub-classes of ```Ctrl``` that don't support ```Font```. I'd rather just test to see if the interface is supported than run through a list of Ctrl types. (Edit: grammar) – Mark Roworth Feb 28 '22 at 10:55
  • 1
    Testing whether the interface is supported is *completely orthogonal* to the decision about implicit/explicit implementation of the interface. – Damien_The_Unbeliever Feb 28 '22 at 11:02
  • @Damien_The_Unbeliever - I get where you're coming from, but, if I go with an implicit declaration, I end up with having a switch statement with an entry for each Ctrl.CtrlTypeCode value (there are a fair few), and then having to coerce Ctrl to Ctrl_BUTTON, or CTRL_CHECKBOX, etc explicitly, making for large and unmanageable code. Ctrl doesn't support Font and shouldn't. The sub-classes do. If I can coerce once, to an interface class, what ends up being dozens of lines of code, becomes 2 lines. Unless you know of another way? – Mark Roworth Feb 28 '22 at 11:10
  • @Damien_The_Unbeliever - also this way, I won't have to revisit the code if I introduce more sub-classes of Ctrl, which will happen. – Mark Roworth Feb 28 '22 at 11:12
  • 1
    You have a misconception that I don't know how to shake from you. If you change to an implicit implementation, **literally none of the code you've written** that performs a implementation check, casts to the interface, and accesses the property will have to change. No, you won't have to suddenly check for specific implementing classes. – Damien_The_Unbeliever Feb 28 '22 at 11:29
  • I'm still not convinced, but thank you for persisting. If I have an object declared as ```Ctrl oCtrl```, surely I can't just write ```oCtrl.Font = ...``` when Font is a property of some of the derived classes. I've tried implementing the interface, but declaring the fulfilment of it as ```Font Font``` rather than ```Font ICtrl_Font```, but VS indicates that I'm not fulfilling the ```ICtrl_Font``` interface. – Mark Roworth Feb 28 '22 at 11:41
  • Specifically the error I get from implicit declaration is: Error 29 'AppData.Ctrl_BUTTON' does not implement interface member 'AppData.ICtrl_Font.Font'. 'AppData.Ctrl_BUTTON.Font' cannot implement 'AppData.ICtrl_Font.Font' because it does not have the matching return type of 'AppData.ICtrl_Font'. – Mark Roworth Feb 28 '22 at 11:44
  • `if (myControl is ICtrl_Font fontCtrl) { doSomethingWithFont(fontCtrl); }`? – ProgrammingLlama Mar 01 '22 at 01:01

0 Answers0