【问题标题】:How to assign a default type to create an optional type parameter?如何分配默认类型以创建可选类型参数?
【发布时间】:2012-11-23 21:38:21
【问题描述】:

我可以解决这个问题,但我很好奇为什么它不起作用:

与您可以为例程创建具有默认值的可选参数相同的方式,例如下面的.....

    public void SomeRoutine(string Title = "Missing")
    {
        // Do something with Title
    }

....为什么不能将默认类型指定为可选参数?

以下示例给出了错误:“'theType' 的默认参数必须是编译时间常数。”

    public void SomeOtherRoutine(Type theType = typeof(MyClass))
    {
        // Do something based on theType
    }

实际的应用程序试图提供枚举包含基类和各种派生类混合的集合的选项,并仅返回感兴趣的类类型:

    public IEnumerable<MyBaseClass> EnumerateWithOptions(Type optionalDerivedClass = typeof(MyBaseClass))
    {
        foreach (MyBaseClass thingy in MyCustomCollection())
        {
            if (thingy.GetType() == optionalDerivedClass)
            { yield return thingy; };
        }
    }

显而易见的替代方法是重载例程以应用默认值,如下所示,但是由于不值得尝试描述的原因,它在我的应用中并不理想。

    public IEnumerable<MyBaseClass> EnumerateWithOptions()
    {
        return EnumerateWithOptions(typeof(MyBaseClass));
    }
    public IEnumerable<MyBaseClass> EnumerateWithOptions(Type optionalDerivedClass)
    {
        foreach (MyBaseClass thingy in MyCustomCollection())
        {
            if (thingy.GetType() == optionalDerivedClass)
            { yield return thingy; };
        }
    }

关于为什么 typeof(MyClass) 不被视为编译时间常数的任何想法,或者对不同方法的任何想法?谢谢。

【问题讨论】:

  • 如果您提供默认值,编译器将为您创建重载。因此,我通常避免提供默认值,而是使用重载方法。
  • 感谢您的评论。当有多个具有默认值的参数时,重载在逻辑上与默认值不同。我提供的示例没有显示它,但是应用程序在 EnumerateWithOptions 例程中有几个参数,每个参数都有默认值 - 包括枚举方向、行 vs 列第一次扫描、子包含、重复键迭代器等。试图表达所有作为重载的选项组合太多了。

标签: c# types parameters default optional


【解决方案1】:

因此您不能使用typeof 或一些Type 值,并且您不想手动创建重载,然后考虑提供null 作为可选参数的默认值:

IEnumerable<MyBaseClass> EnumerateWithOptions(Type optionalDerivedClass = null)
{
    if (optionalDerivedClass == null)
        return MyCustomCollection();

    return MyCustomCollection()
        .Where(thingy => thingy.GetType() == optionalDerivedClass);
}

如果您可以使用泛型参数而不是Type 对象,那么您可以通过Enumerable.OfType&lt;T&gt;() 过滤集合:

IEnumerable<MyBaseClass> result = MyCustomCollection().OfType<YourType>();

【讨论】:

  • 使用 null 最接近直接解决我最初的问题,即如何使用默认值设置类型参数。我仍然不确定为什么 typeof(MyClass) 不被视为编译时间常数。谢谢lazyberezovsky,我会将此标记为正确答案。
  • @user1689175 typeof() 不被视为常量,因为它是对System.Type.GetTypeFromHandle 的方法调用。而且您不能使用方法调用(仅在运行时发生)来设置常量。
【解决方案2】:

你可以这样做

  public IEnumerable<MyBaseClass> EnumerateWithOptions<T>()
  {
      foreach (MyBaseClass thingy in MyCustomCollection())
      {
         if (thingy.GetType() == typeof(T))
         { yield return thingy; };
      }
  }

用法

var list = EnumerateWithOptions<MyBaseClass>();
var list = EnumerateWithOptions<MyDerivedClass>();

【讨论】:

  • 虽然这并不能直接回答我最初关于如何指定具有默认值的类型参数的问题 - 我真的很喜欢这种方法并将尝试实现它。谢谢你的好建议!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 2021-06-14
  • 1970-01-01
相关资源
最近更新 更多