【问题标题】:Constructor constraint on generic types or simply check for constraint within my generic type constructor?泛型类型的构造函数约束还是简单地检查我的泛型类型构造函数中的约束?
【发布时间】:2010-07-13 20:17:41
【问题描述】:

我有一个泛型类 DirectorySource<T>,它依赖于接口 IDirectorySearch<T>

两者都是泛型并且具有相同的类型约束:

public class DirectorySource<T> where T : IDirectoryEntry { }

public interface IDirectorySearcher<T> where T : IDirectoryEntry { }

因此,例如,当我想要一个来源来操纵组时,我会这样做:

IDirectorySearcher<Group> groupSearcher = new GroupSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource(groupSearcher);

我希望提出的是强制,当我的泛型类型 DirectorySource&lt;T&gt;DirectorySource&lt;Group&gt; 类型时,我的搜索者是 GroupSearcher,我不希望一个能够传入例如UserSearcher

我已阅读以下文章:

  1. C#: Generic types that have a constructor?;
  2. An Introduction to C# Generics;
  3. new Constraint (C# Reference)

而且我似乎不知道如何在我的班级中处理这种约束。至于现在,我有以下几点:

public class DirectorySource<T> where T : IDirectoryEntry {
    public DirectorySource(IDirectorySearcher<T> searcher) {
        Searcher = searcher;
    }

    public IDirectorySearcher<T> Searcher { get; private set; }
}

然后,我也有以下内容:

public class GroupSearcher : IDirectorySearcher<Group> {

    public GroupSearcher(DirectoryEntry root, SearchScope scope) {
        NativeSearcher = new DirectorySearcher();
        NativeSearcher.SearchRoot = root;
        NativeSearcher.SearchScope = scope;
    }

    // Implementing interface...
}

我不能只替换 Searcher 属性类型,因为这会导致我的泛型类变为非泛型。

关于我应该如何完成我想要完成的事情的构造函数约束,我有什么想法或不正确理解吗?

编辑#1

我想这样做的原因是因为可以做到以下几点:

IDirectorySearcher<User> userSearcher = new UserSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource<Group>(userSearcher);

这对我来说似乎不正确......

1.我在这里遗漏了一些明显的东西吗? =)

提前致谢!

【问题讨论】:

  • @SLaks:我的 EDIT #1 是否更清楚?否则,我会努力做到这一点。

标签: c# generics constructor constraints


【解决方案1】:

我希望提出的是强制,当我的泛型类型 DirectorySource 是 DirectorySource&lt;Group&gt; 输入,我的搜索者是 GroupSearcher。

为什么?这与将搜索器功能封装到界面中的观点背道而驰,肯定吗?您不应该关心实现是什么,只要它可以搜索正确类型的条目即可。

我认为构造函数约束在这里并不重要——这只允许您创建一个不带参数的 T 的新实例...

编辑:我看不出您提出的问题实际上是个问题。我们来看代码:

IDirectorySearcher<User> userSearcher = new UserSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource<Group>(userSearcher);

所以这里TDirectorySource&lt;T&gt;Group。现在,构造函数将要求您传入 IDirectorySearcher&lt;Group&gt; - 据我所知,userSearcher 不是。所以这段代码不会编译,这就是你想要的。问题出在哪里?

【讨论】:

  • 感谢您的回答。我之所以要这样做是因为,就目前而言,可以执行以下操作:(请参阅我的编辑#1)。
  • 如果您看到我的 EDIT #1,您现在可能会更好地理解我为什么要强制它或约束或任何东西到 GroupSearcher,继续我的示例。
  • 你觉得我应该怎么做?我的设计不好吗? =S
  • @Will:我不清楚这将如何编译。您将尝试创建一个 DirectorySource&lt;Group&gt; 传递未实现 IDirectorySearcher&lt;Group&gt; 的东西,因此据我所知它不会编译。你试过了吗?
  • 我对泛型很陌生,我认为来自DirectorySource&lt;T&gt;T 和来自IDirectorySearcher&lt;T&gt;T 是完全独立的,即使T 在来源。为了回答你的问题,我还没有测试它,因为我已经在 VB.NET 2.0 中编写了这段代码,这不允许我使用我曾经在 C# 中使用的大量功能,所以我用 C# 重写它的方式我会这样做,然后在所有测试后使用从 C# 到 VBNET 的转换器。此外,通过您的编辑,我认为没有任何问题! =) 谢谢,这有帮助! =)
【解决方案2】:

您是否考虑过:

public class DirectorySource<TValue, TSearcher> 
            where TValue : IDirectoryEntry 
            where TSearcher : IDirectorySearcher<T>, new() 
{ 
    public DirectorySource(TSearcher seacher) 
    { 
        Searcher = seacher
    } 

    public TSearcher Searcher { get; private set; } 
} 

IDirectorySearcher<Group> groupSearcher = new GroupSearcher(ROOT, SCOPE);     
var  groups = new DirectorySource<Group, GroupSearcher>(groupSearcher); 

【讨论】:

  • 我不认为这是必要的......我不明白为什么会这样。查看我的编辑。
  • 我在某些我认为有意义的情况下也这样做了。我的印象是,这种方法可以编译,这样对 TSearcher 实例上的方法的任何调用都将直接调用实际类型的方法,而不是通过接口进行虚拟调用。我尝试了这一点,发现我的理解实际上并非如此(根据 ILDASM)。并不是说性能对我来说通常如此重要,以至于我关心呼叫是否是虚拟的,但至少这是我能想到的这种方法的一个好处。我错过了什么吗?
  • -bonk self- 好吧,我觉得我很傻;查看 IL 并没有多大用处,因为 JIT 编译器在运行时有效地评估了泛型参数(如果我不在基地,请有人纠正我)。因此,真正重要的是 JIT 编译器如何处理它。我认为我读到了一些提示 JIT 编译器在这种情况下不会使用接口方法分派的内容,但也许我错了。
  • @Jon,我假设他真的非常希望 Searcher 属性返回 GroupSearcher 而不仅仅是 IDirectorySearcher&lt;Group&gt;
【解决方案3】:

我认为你要得到你想要的东西的唯一方法(据我所知)是如果你向IDirectorySearcher 添加一个GetSource 方法,它返回一个IDirectorySource&lt;T&gt; 的实现。

【讨论】:

  • +1 不错的主意。然而,当我想应用待处理的更改时,这是我的来源的职责,而不是搜索者的职责。换句话说,我想让我的GroupSearcher 成为我的DirectorySource 的一部分,但是当我想将这两者合并在一起时,这是一个非常糟糕的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 2011-09-10
相关资源
最近更新 更多