Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. then the new student submits their answer to ...

then the new student submits their answer to ...

Scheduled Pinned Locked Moved C#
csharpasp-nettutorial
11 Posts 5 Posters 25 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    BillWoodruff
    wrote on last edited by
    #1

    write a c# 8 Core 7 example of InterFace and Abstract class:

    namespace _07_08_2023_test
    {
    public interface IFace1
    {
    DateTime DTimeUTC { get; }
    }

    public interface IFace2
    {
        string FirstName { get; }
        string LastName { get; }
    }
    
    public abstract class Abs1 : IFace1, IFace2
    {
        public DateTime DTimeUTC {get; } = DateTime.Now.ToUniversalTime();
        public string FirstName { get; protected set; }
        public string LastName { get; protected set; }
    
        public string FullName
        {
            get => $"{FirstName} ... {LastName}";
        }
    }
    
    public class StudentMess : Abs1
    {
        public StudentMess(string fname, string lname)
        {
            FirstName = fname;
            LastName = lname;
        }
    }
    

    }

    And, said new student says: "it compiles, and I can do this:"

        private void Form1\_Load(object sender, EventArgs e)
        {
            StudentMess smess = new StudentMess("new", "confused");
        }
    

    And, you shake your head.

    «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

    P 1 Reply Last reply
    0
    • B BillWoodruff

      write a c# 8 Core 7 example of InterFace and Abstract class:

      namespace _07_08_2023_test
      {
      public interface IFace1
      {
      DateTime DTimeUTC { get; }
      }

      public interface IFace2
      {
          string FirstName { get; }
          string LastName { get; }
      }
      
      public abstract class Abs1 : IFace1, IFace2
      {
          public DateTime DTimeUTC {get; } = DateTime.Now.ToUniversalTime();
          public string FirstName { get; protected set; }
          public string LastName { get; protected set; }
      
          public string FullName
          {
              get => $"{FirstName} ... {LastName}";
          }
      }
      
      public class StudentMess : Abs1
      {
          public StudentMess(string fname, string lname)
          {
              FirstName = fname;
              LastName = lname;
          }
      }
      

      }

      And, said new student says: "it compiles, and I can do this:"

          private void Form1\_Load(object sender, EventArgs e)
          {
              StudentMess smess = new StudentMess("new", "confused");
          }
      

      And, you shake your head.

      «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      Judging by your message here, and earlier posts, I guess that you're trying to figure out what problem is being solved by the new interface implementations capability being introduced in the language now. Would that be fair to say? If so, you aren't actually using that capability in your example. What am I missing here? -- edited to add the word using

      Advanced TypeScript Programming Projects

      B 2 Replies Last reply
      0
      • P Pete OHanlon

        Judging by your message here, and earlier posts, I guess that you're trying to figure out what problem is being solved by the new interface implementations capability being introduced in the language now. Would that be fair to say? If so, you aren't actually using that capability in your example. What am I missing here? -- edited to add the word using

        Advanced TypeScript Programming Projects

        B Offline
        B Offline
        BillWoodruff
        wrote on last edited by
        #3

        Pete O'Hanlon wrote:

        what problem is being solved by the new interface implementations capability being introduced in the language now.

        Thanks, Pete Yes, i am asking what advantages are being offered to make what, imho, is a classic pillar of modern programming a different construct.

        Pete O'Hanlon wrote:

        What am I missing here?

        i guess my "student mess" example did not convey the difficulty in getting a strategic sense of when to use Interface and Abstract. bill is missing many things right now, including (too often) ability to concentrate, i apologize for my lack of thoroughness.

        «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

        P 1 Reply Last reply
        0
        • P Pete OHanlon

          Judging by your message here, and earlier posts, I guess that you're trying to figure out what problem is being solved by the new interface implementations capability being introduced in the language now. Would that be fair to say? If so, you aren't actually using that capability in your example. What am I missing here? -- edited to add the word using

          Advanced TypeScript Programming Projects

          B Offline
          B Offline
          BillWoodruff
          wrote on last edited by
          #4

          using C# 8 new Interface features:

          public interface IExampleInterface
          {
          // A method with a default implementation
          void DefaultMethod()
          {
          Console.WriteLine("This is the default implementation of DefaultMethod.");
          }

          // A static method
          static void StaticMethod()
          {
              Console.WriteLine("This is a static method in an interface.");
          }
          

          }

          And ... in C#9: Init-only setters; Target-typed new expressions ... in C#10: Record structs. imho, Interface is becoming very different, and learning the strategic use of the new features much more difficult.

          «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

          L Richard DeemingR 2 Replies Last reply
          0
          • B BillWoodruff

            using C# 8 new Interface features:

            public interface IExampleInterface
            {
            // A method with a default implementation
            void DefaultMethod()
            {
            Console.WriteLine("This is the default implementation of DefaultMethod.");
            }

            // A static method
            static void StaticMethod()
            {
                Console.WriteLine("This is a static method in an interface.");
            }
            

            }

            And ... in C#9: Init-only setters; Target-typed new expressions ... in C#10: Record structs. imho, Interface is becoming very different, and learning the strategic use of the new features much more difficult.

            «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            I agree with your final statement. I would be interested in knowing what new devs, coming to .NET now, think of it.

            1 Reply Last reply
            0
            • B BillWoodruff

              using C# 8 new Interface features:

              public interface IExampleInterface
              {
              // A method with a default implementation
              void DefaultMethod()
              {
              Console.WriteLine("This is the default implementation of DefaultMethod.");
              }

              // A static method
              static void StaticMethod()
              {
                  Console.WriteLine("This is a static method in an interface.");
              }
              

              }

              And ... in C#9: Init-only setters; Target-typed new expressions ... in C#10: Record structs. imho, Interface is becoming very different, and learning the strategic use of the new features much more difficult.

              «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

              Richard DeemingR Offline
              Richard DeemingR Offline
              Richard Deeming
              wrote on last edited by
              #6

              Just to make things more confusing, a static interface member with a default implementation must be marked as virtual, otherwise you'll get a compiler error when you try to use it:

              public interface IFoo
              {
              static void S() => Console.WriteLine("Default");
              }

              static void Test() where T : IFoo
              {
              // CS0704 Cannot do non-virtual member lookup in 'T' because it is a type parameter
              T.S();
              }

              If you don't provide a default implementation, you have to mark it as abstract. In order to provide its own implementation, a class has to declare the method as public, which doesn't match the interface declaration, leading to more confusion:

              public interface IFoo
              {
              static virtual void S() => Console.WriteLine("Default");
              }

              public class Foo : IFoo
              {
              // Why is this never called?
              static void S() => Console.WriteLine("Overridden");
              }

              static void Test() where T : IFoo
              {
              T.S();
              }

              Test(); // Output: "Default"

              You can alleviate that by marking the interface method as public:

              public interface IFoo
              {
              public static virtual void S() => Console.WriteLine("Default");
              }

              But IMO, adding access modifiers to interface members goes against the "ethos" of interfaces. If I can see the interface, then I should be able to access all members of that interface, so they shouldn't need to be marked as public. And having some members protected or private just seems like nonsense! And if that's still not confusing enough, the implementation of the static method cannot use the override modifier, even though it's required when you provide an implementation of a virtual / abstract method from a base class:

              public class Foo : IFoo
              {
              // CS0112 A static member cannot be marked as 'override'
              public static override void StaticMethod() => Console.WriteLine("Overridden");
              }


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

              B 1 Reply Last reply
              0
              • B BillWoodruff

                Pete O'Hanlon wrote:

                what problem is being solved by the new interface implementations capability being introduced in the language now.

                Thanks, Pete Yes, i am asking what advantages are being offered to make what, imho, is a classic pillar of modern programming a different construct.

                Pete O'Hanlon wrote:

                What am I missing here?

                i guess my "student mess" example did not convey the difficulty in getting a strategic sense of when to use Interface and Abstract. bill is missing many things right now, including (too often) ability to concentrate, i apologize for my lack of thoroughness.

                «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                P Offline
                P Offline
                Pete OHanlon
                wrote on last edited by
                #7

                So, the biggest advantage of the interface implementation is that it allows you to add features to an interface without breaking existing implementations. Imagine that you have the following interface:

                public interface MyRestApi
                {
                string ApiName { get; set; }
                int Version { get; set; }
                string RequestBody { get; set; }
                }

                Now, as an application API author, you have published this interface and your component uses it quite successfully; more importantly, you have shipped this out and 1/4 million happy customers are using your component and are supplying their own implementations of this API into your component. Let's say that you have decided that you want to upgrade your component and add a new feature to this interface; you have decided that it will support a check-sum. You don't want to upset those customers who are already using your component by breaking their build by adding a new property they have to supply. You don't want to stop those customers from having to change their code to use a version 2 of this API; which could be significant disruption. Finally, you want the customers to be able to use your upgraded capability, and adjust to supplying their own checksum implementation when they are ready. That's what this capability provides; you can upgrade the interface by supplying your own default implementation, satisfying the ability not to break things, and the consumer can upgrade the implementation if they want to later on. So, the next version of your component has this interface

                public interface MyRestApi
                {
                string ApiName { get; set; }
                int Version { get; set; }
                string RequestBody { get; set; }
                uint Checksum()
                {
                using CRC32 crc32 = new();
                byte[] data = Encoding.UTF8.GetBytes(RequestBody);
                byte[] hashBytes = crc32.ComputeHash(data);
                return BitConverter.ToUInt32(hashBytes, 0);
                }

                }

                Now, I've just typed this code into the text window here so it may not be 100% correct, but this is one of the reasons for this capability.

                Advanced TypeScript Programming Projects

                1 Reply Last reply
                0
                • Richard DeemingR Richard Deeming

                  Just to make things more confusing, a static interface member with a default implementation must be marked as virtual, otherwise you'll get a compiler error when you try to use it:

                  public interface IFoo
                  {
                  static void S() => Console.WriteLine("Default");
                  }

                  static void Test() where T : IFoo
                  {
                  // CS0704 Cannot do non-virtual member lookup in 'T' because it is a type parameter
                  T.S();
                  }

                  If you don't provide a default implementation, you have to mark it as abstract. In order to provide its own implementation, a class has to declare the method as public, which doesn't match the interface declaration, leading to more confusion:

                  public interface IFoo
                  {
                  static virtual void S() => Console.WriteLine("Default");
                  }

                  public class Foo : IFoo
                  {
                  // Why is this never called?
                  static void S() => Console.WriteLine("Overridden");
                  }

                  static void Test() where T : IFoo
                  {
                  T.S();
                  }

                  Test(); // Output: "Default"

                  You can alleviate that by marking the interface method as public:

                  public interface IFoo
                  {
                  public static virtual void S() => Console.WriteLine("Default");
                  }

                  But IMO, adding access modifiers to interface members goes against the "ethos" of interfaces. If I can see the interface, then I should be able to access all members of that interface, so they shouldn't need to be marked as public. And having some members protected or private just seems like nonsense! And if that's still not confusing enough, the implementation of the static method cannot use the override modifier, even though it's required when you provide an implementation of a virtual / abstract method from a base class:

                  public class Foo : IFoo
                  {
                  // CS0112 A static member cannot be marked as 'override'
                  public static override void StaticMethod() => Console.WriteLine("Overridden");
                  }


                  "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                  B Offline
                  B Offline
                  BillWoodruff
                  wrote on last edited by
                  #8

                  Richard Deeming wrote:

                  adding access modifiers to interface members goes against the "ethos" of interfaces.

                  "ethos" ... right word ! i am curious which versions of future C#/.NET your thorough review of future "features" are based on ... aside: i am still hung-up on the fact that C# inner classes within outer classes "mean nothing" ... unless, of course you want to make them private and only use/manipulate then from within their containing classes ... i am probably still in recovery from 'Self in SmallTalk, "super" in Java ... my problem ! cheers, bill `

                  «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                  Richard DeemingR 2 Replies Last reply
                  0
                  • B BillWoodruff

                    Richard Deeming wrote:

                    adding access modifiers to interface members goes against the "ethos" of interfaces.

                    "ethos" ... right word ! i am curious which versions of future C#/.NET your thorough review of future "features" are based on ... aside: i am still hung-up on the fact that C# inner classes within outer classes "mean nothing" ... unless, of course you want to make them private and only use/manipulate then from within their containing classes ... i am probably still in recovery from 'Self in SmallTalk, "super" in Java ... my problem ! cheers, bill `

                    «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                    Richard DeemingR Offline
                    Richard DeemingR Offline
                    Richard Deeming
                    wrote on last edited by
                    #9

                    BillWoodruff wrote:

                    i am curious which versions of future C#/.NET your thorough review of future "features" are based on ...

                    Static interface methods were added in preview mode for C# 10, and released with C# 11: Preview Features in .NET 6 - Generic Math - .NET Blog[^] Explore static virtual members in interfaces | Microsoft Learn[^] Default interface implementations were added in C# 8: Default interface methods - C# 8.0 draft feature specifications | Microsoft Learn[^]


                    "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                    "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                    1 Reply Last reply
                    0
                    • B BillWoodruff

                      Richard Deeming wrote:

                      adding access modifiers to interface members goes against the "ethos" of interfaces.

                      "ethos" ... right word ! i am curious which versions of future C#/.NET your thorough review of future "features" are based on ... aside: i am still hung-up on the fact that C# inner classes within outer classes "mean nothing" ... unless, of course you want to make them private and only use/manipulate then from within their containing classes ... i am probably still in recovery from 'Self in SmallTalk, "super" in Java ... my problem ! cheers, bill `

                      «The mind is not a vessel to be filled but a fire to be kindled» Plutarch

                      Richard DeemingR Offline
                      Richard DeemingR Offline
                      Richard Deeming
                      wrote on last edited by
                      #10

                      Some more confusion for you from Reddit, relating to the older default interface implementation rather than the newer static interface members:

                      https://www.reddit.com/r/csharp/comments/15o30l1/explicit_interface_reabstraction/[^]:

                      I had a question while reading the Microsoft docs on interfaces https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction[^] In the docs, they give the example

                      interface IA
                      {
                      void M() { WriteLine("IA.M"); }
                      }
                      interface IB : IA
                      {
                      abstract void IA.M();
                      }
                      class C : IB { } // error: class 'C' does not implement 'IA.M'.

                      Which forces you to implement method M in class C. However, you can also define the interface IB this way, which also forces method M to be defined in class C.

                      interface IA
                      {
                      void M() { WriteLine("IA.M"); }
                      }
                      interface IB : IA
                      {
                      new void M();
                      }
                      class C : IB { } // error: class 'C' does not implement 'IB.M'.

                      I did notice there is a small difference, where since in the second example, interface IB is shadowing IA, the error message changes, but in practice, is there any difference between these two?


                      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                      S 1 Reply Last reply
                      0
                      • Richard DeemingR Richard Deeming

                        Some more confusion for you from Reddit, relating to the older default interface implementation rather than the newer static interface members:

                        https://www.reddit.com/r/csharp/comments/15o30l1/explicit_interface_reabstraction/[^]:

                        I had a question while reading the Microsoft docs on interfaces https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction[^] In the docs, they give the example

                        interface IA
                        {
                        void M() { WriteLine("IA.M"); }
                        }
                        interface IB : IA
                        {
                        abstract void IA.M();
                        }
                        class C : IB { } // error: class 'C' does not implement 'IA.M'.

                        Which forces you to implement method M in class C. However, you can also define the interface IB this way, which also forces method M to be defined in class C.

                        interface IA
                        {
                        void M() { WriteLine("IA.M"); }
                        }
                        interface IB : IA
                        {
                        new void M();
                        }
                        class C : IB { } // error: class 'C' does not implement 'IB.M'.

                        I did notice there is a small difference, where since in the second example, interface IB is shadowing IA, the error message changes, but in practice, is there any difference between these two?


                        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                        S Offline
                        S Offline
                        Sandeep Mewara
                        wrote on last edited by
                        #11

                        I would prefer the second one as it completely hides IA from C (which mostly I would want when I setting up like this). This also suggests me that the 1st implementation is for scenarios where you don't want to hide and be much more explicit about who is asking to implement (also IB is mostly playing middlemen for some reason known/unknown).

                        Latest CodeProject post: Quick look into Machine Learning workflow How to solve Word Ladder Problem? To read all my blog posts, visit: Learn by Insight...

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups