C#:内部和公共接口,自动实现的属性,但结构...

时间:2017-02-08 11:36:38

标签: c# struct interface automatic-properties

我知道有一个模式涉及部分类来实现一个具有setSet属性的类,但是从外部是只读的,比如

// This is just the non-working example to get the idea of what I want it to do across

public interface IMyReadable
{
    int Property1 { get; }
    string Property2 { get; }
}

internal interface IMyEditable : IMyReadable
{
    int Property1 { get; set; }
    string Property2 { get; set;}
}

public class Implementation : IMyEditable
{
    public int Property1 { get; internal set; }
    public string Property2 { get; internal set;}
}

因为您无法定义内部设置'在一个界面中。它可以用于例如类。 https://stackoverflow.com/a/42082500/6155053

...但如果我想为结构做这件事怎么办?

我知道,结构通常应该是完全只读的,但是有多个不同的结构实现实现接口,然后能够首先实例化它们并在之后从程序集内部通过属性启动它们属性会很好,例如在工厂类中,无需为每个不同的实现(通过他们的c' tors等)编写每个界面属性的设置。

这将允许我做类似

的事情
// non-sense, but explanatory code snippet
[…]
var structs = new HashSet<IMyEditable>();
structs.Add(new MyEditableImplementation1());
structs.Add(new MyEditableImplementation2());
structs.Add(new MyEditableImplementation3());

int i = 0;
foreach(IMyEditable s in structs)
{
    s.Property1 = ++i;
    s.Property2 = i.ToString();
}

// ...and still be able to set custom properties only some of the implementations
// have afterwards, etc., and when you then return, for example do:

return structs.Cast<IMyReadable>();

随着接口实现次数的增加,将节省大量的样板用于初始化。

然而,由于结构总是密封的,并且不能从基础结构继承... ...如何在不失去自动实现属性的优势的情况下这样做(如果我和#我会这样做39; d使用代理属性和每个结构中的共享私有字段来执行它 - 再次,这意味着很多样板代码,只在另一个地方。)

这可能吗?如果是这样,怎么样?

编辑:添加第二个样本以解释所需的用法

1 个答案:

答案 0 :(得分:-1)

这个怎么样?

enter image description here

IReader.cs(ClassLibrary1)

namespace ClassLibrary1
{
    public interface IReader
    {
        int Property1 { get; }
        string Property2 { get; }
    }
}

IWriter.cs(ClassLibrary1)

namespace ClassLibrary1
{
    internal interface IWriter : IReader
    {
        new int Property1 { get; set; }
        new string Property2 { get; set; }
    }
}

SomeObject.cs(ClassLibrary1)

namespace ClassLibrary1
{
    internal class SomeObject : IWriter
    {
        public int Property1 { get; set; }
        public string Property2 { get; set; }
    }
}

Worker.cs(ClassLibrary1)

namespace ClassLibrary1
{
    using System.Collections.Generic;
    using System.Linq;

    public static class Worker
    {
        // NOTE: Thanks to internal on the IWriter, you can't return IWriter here.
        public static IEnumerable<IReader> DoSomething()
        {
            var structs = new HashSet<IWriter>();
            structs.Add(new SomeObject());
            structs.Add(new SomeObject());
            structs.Add(new SomeObject());

            int i = 0;
            foreach (IWriter s in structs)
            {
                s.Property1 = ++i;
                s.Property2 = i.ToString();
            }

            return structs.Cast<IReader>();
        }
    }
}

Program.cs(ConsoleApplication3)

namespace ConsoleApplication3
{
    using System.Collections.Generic;
    using System.Linq;
    using ClassLibrary1;

    public class Program
    {
        private static void Main(string[] args)
        {
            // NOTE: You can't cast the structs to IWriter here.
            var structs = Worker.DoSomething();

            // This will not compile:
            // (structs.FirstOrDefault() as IWriter).Property1 = 10
        }
    }
}

请注意:

  • IWriterinternal,这意味着你无法通过它/在外面使用它 ClassLibrary1。完美,只有你的'内部'可以在它上面工作 对外界你只能暴露IReader,这就是我们 做。
  • 在控制台应用程序中,您无法将对象强制转换为IWriter。哪个好。

有趣的是,'立即窗口'允许我将结构转换为IWriter,但我认为它使用反射,这在编译时是不允许的,所以你很好!

相关问题