簡體   English   中英

受保護的構造函數:where new() 約束

[英]Protected constructor for :where new() constraint

我使用裝飾模式編寫了 class 以避免 inheritance 問題。 我制作了工廠方法來強制組件復制它的實例。 代碼將是這樣的:

public interface IFoo
{
    int Bar { get; set; }
}

public class Foo : IFoo
{
    public int Bar { get; set; }

    public Foo() { }
}

public abstract class FooDecorator : IFoo
{
    protected IFoo _Foo;
    
    public int Bar
    {
        get
        {
            return _Foo.Bar;
        }
        set
        {
            _Foo.Bar = value;
        }
    }

    public static TOutput Create<TOutput, TInput>(TInput foo)
            where TOutput : FooDecorator, new()
            where TInput : IFoo, new()
    {
        var copy = new TInput
        {
            Bar = foo.Bar
        };
        return new TOutput { _Foo = copy };
        }
    }
}

public class FooDecoratorImpl : FooDecorator
{
    public FooDecoratorImpl() {} // This is necessary only for new() constraint. I'd like to hide it.

    public static FooDecoratorImpl Create<T>(T foo) where T : IFoo, new()
    {
        return Create<FooDecoratorImpl, T>(foo);
    }
}

Foo foo = new Foo() { Bar = 1 };

FooDecoratorImpl decorator = FooDecoratorImpl.Create(foo);
Console.WriteLine(decorator.Bar) // show "1"

FooDecoratorImpl unintended = new FooDecoratorImpl(); // I don't like to do this!

由於默認構造函數在FooDecorator.Create(foo)方法上是只讀的,我希望它的訪問修飾符設置為protected (我知道這不起作用,因為FooDecorator不是FooDecoratorImpl的派生類型,而是另一種方式輪。)以防止意外實例化。 但是構造函數需要是公開的。 如何限制僅在FooDecorator.Create(foo)上加載構造函數?

使用帶有常規構造函數的泛型類:

public abstract class FooDecorator<TSource> : IFoo
    where TSource : IFoo, new()
{
    protected IFoo _Foo;
    
    public int Bar
    {
        get
        {
            return _Foo.Bar;
        }
        set
        {
            _Foo.Bar = value;
        }
    }

    protected FooDecorator(TSource foo)
    {
        // TODO: null check foo
        var copy = new TSource
        {
            Bar = foo.Bar
        };

        _Foo = copy;
    }
}

public class FooDecoratorImpl<TSource> : FooDecorator<TSource>
    where TSource : IFoo, new()
{
    public FooDecoratorImpl(TSource foo)
        : base(foo)
    {
    }
}

Foo foo = new Foo() { Bar = 1 };

var decorator = new FooDecoratorImpl<Foo>(foo);
Console.WriteLine(decorator.Bar) // show "1"

// this won't compile
var unintended = new FooDecoratorImpl<Foo>(); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM