【发布时间】:2016-06-30 09:30:08
【问题描述】:
MSDN docs 包含关于隐式转换的部分:
var s = $"hello, {name}";
System.IFormattable s = $"Hello, {name}";
System.FormattableString s = $"Hello, {name}";
从第一个字符串开始,内插字符串的原始类型是string。好的,我可以理解,但是……我意识到字符串没有实现IFormattable。所以它看起来像是来自编译器的一些魔法,类似于它对 lambdas 所做的事情。
现在猜猜这段代码的输出:
void Main()
{
PrintMe("Hello World");
PrintMe($"{ "Hello World"}");
}
void PrintMe(object message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
//void PrintMe(string message)
//{
// Console.WriteLine("I am a string " + message.GetType().FullName);
//}
void PrintMe(IFormattable message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
提示:
我是 System.String
我是 System.Runtime.CompilerServices.FormattableStringFactory+ConcreteFormattableString
如果你从第二种方法中移除 cmets,你会得到:
我是一个字符串 System.String
我是字符串 System.String
好的
可能是我不太了解重载分辨率,但是C# spec 的 14.4.2 暗示首先定义了传递参数的类型,但是 lambdas 又是如何工作的?
void Main()
{
PrintMe(() => {});
PrintMe(() => {});
}
void PrintMe(object doIt)
{
Console.WriteLine("I am an object");
}
//void PrintMe(Expression<Action> doIt)
//{
// Console.WriteLine("I am an Expression");
//}
void PrintMe(Action doIt)
{
Console.WriteLine("I am a Delegate");
}
删除 cmets 和...
CS0121 调用在以下方法之间不明确或 属性:'UserQuery.PrintMe(Expression)' 和 'UserQuery.PrintMe(Action)'
所以我不明白这里编译器的行为。
更新:
更糟糕的是,我检查了扩展方法的这种行为:
void Main()
{
PrintMe("Hello World");
PrintMe($"{"Hello World"}");
"Hello World".PrintMe();
$"{"Hello World"}".PrintMe();
}
void PrintMe(object message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
void PrintMe(IFormattable message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
public static class Extensions
{
public static void PrintMe(this object message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
public static void PrintMe(this IFormattable message)
{
Console.WriteLine("I am a " + message.GetType().FullName);
}
}
现在我有这样的:
我是一个 System.String
我是 System.Runtime.CompilerServices.FormattableStringFactory+ConcreteFormattableString
我是 System.String
我是 System.String
【问题讨论】:
-
您尝试过
PrintMe与FormattableString而不是IFormattable的方法吗? -
摆脱
() => {}是Action的想法。它不是。这是一个 lambda 表达式。它可以转换为Action,或任何其他具有正确签名的委托类型(如MethodInvoker或ThreadStart)。它也可以转换为Expression<Action>,或任何其他具有正确签名的Expression<TDelegate>。这就是为什么它是模棱两可的。PrintMe(Action)和PrintMe(Expression<Action>)同样有效。 -
@DovydasSopa 还没有。
-
@Dennis_E 是的,这就是我尝试两者的原因。而且我希望插值字符串有同样的歧义。但事实并非如此。
-
我猜原始类型是一种特殊的编译器类型,称为“插值字符串”,可以转换为其他类型。就像 lambda 表达式和方法组一样。所以它是 CLR 中没有表示的特殊类型。
标签: c# string type-inference overloading string-interpolation