2012-12-05 38 views
0

我可以解决这个问题,但我很好奇,为什么它不会工作:如何分配默认类型以创建可选的类型参数?

在,你可以创建一个程序,默认值的可选参数,例如下面的一个同样的方式... ..

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

....为什么你不能指定一个默认的类型作为一个可选的参数?

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

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)不被认为是一个编译时间常量,或任何想法不同的方法?谢谢。

+0

如果你提供一个默认值时,编译器为您创造过载。因此,我通常避免提供默认值并使用重载方法。 – Trisped

+0

感谢您的评论。当有多个参数与默认值时,过载在逻辑上与默认值不同。我提供的示例没有显示它,但应用程序在EnumerateWithOptions例程中有几个参数,每个参数都具有默认值 - 包括枚举方向,行与列第一次扫描,子级包含,重复键迭代器等。试图表达所有作为重载的选项组合太多了。 – user1689175

回答

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<T>()过滤收集:

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

null的使用最接近我直接解决如何使用默认值设置类型参数的原始问题。我仍然不确定为什么typeof(MyClass)不被视为编译时间常量。谢谢lazyberezovsky,我会将其标记为正确的答案。 – user1689175

+0

@ user1689175 typeof()不被视为常量,因为它是对'System.Type.GetTypeFromHandle'的方法调用。你不能使用方法调用(只发生在运行时)来设置常量。 –

0

你可以做这样的事情

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>(); 
+0

尽管这并不直接回答我如何使用默认值指定类型参数的原始问题 - 我非常喜欢这种方法,并会尝试实现它。感谢您的伟大建议! – user1689175

相关问题