Default interface methods and default values for Auto Properties

自古美人都是妖i 提交于 2021-01-27 13:00:28

问题


Given that an auto property compiles to a get_method, a set_method and a private variable and since C# 8 is introducing default interface methods

Can properties in Interfaces have default implementations?

Especially a get only property?


回答1:


Yes.

Auto properties aren't a special type of property. They are a convenience feature that generates the code needed to store property values in a backing field.

You can specify a default implementation for properties, both for getters and setters. You can try the following code in Sharplab.io

public interface IDimensions
{
    int Height {get;set;}
    int Width {get;set;}
    int Depth {get;set;}

    int Weight { get=>0; set{} }
    int Density { get=> Weight==0?0:Height*Width*Depth/Weight ; }
}

public class Box:IDimensions
{
    public int Height{get;set;}
    public int Width{get;set;}
}

Versioning

This demonstrates the versioning scenario. Box implemented a version of IDimensions that only included Height, Width.

Weight was added later with a default implementation that returns 0 and ignores writes. Density was added with a default implementation that returns the volume/density of a box, or 0 if there's no valid weight. Box didn't have to change even though the interfade did. Even the code generated by the compiler doesn't show any changes to the Box class.

Classes can replace the default implementations with their own. Nothing prevents Box from adding int Weight {get;set;} in the future.

The default implementations are available only through the interface :

IDimensions box=new Box();
Console.WriteLine(box.Density);

Traits

The other scenario handled by default implementations is traits.

Let's assume I want to add the IDensity trait to any type of item. In most cases, I'd only need the volume and weight of an item to calculate its density :

public interface IDensity
{
    int Density 
    { 
        get 
        {
            var weight=getWeight();
            if (weight==0) return 0;
            return getVolume()/weight;
        }
    }

    abstract int getWeight();
    abstract int getVolume();
}

This trait will return a simplistic density calculation and force the type it's applied to to implement the int getWeight() and an int getHeight() methods:

public class Crate:IDensity
{
    //Dummy numbers
    public int getWeight()=>55;
    public int getVolume()=>100;
}

public class C {
    public void M() {
        IDensity box=new Cake();
        Console.WriteLine(box.Density);
    }
}

Another container could override that implementation with its own. Perhaps the container has a complex shape :

public class WeddingCake:IDensity
{
    public int getWeight()=>5;
    public int getVolume()=>getWeight()/Density;
    public int Density=>2;
}

The Sharplab.io link for this example is here




回答2:


No.


The proposal says:

Interfaces may not contain instance state. While static fields are now permitted, instance fields are not permitted in interfaces. Instance auto-properties are not supported in interfaces, as they would implicitly declare a hidden field.

(source)

See also the Channel 9 interview A Preview of C# 8 with Mads Torgersen where they talk about Default Interface Implementations among other things.


Default interface methods is not included in C# 8.0 (beta) which was released with Visual Studio 2019 Preview 1. At the time of writing, the default interface methods prototype is still in development. Refer to Champion "default interface methods".



来源:https://stackoverflow.com/questions/53700939/default-interface-methods-and-default-values-for-auto-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!