为什么这在C#中是不可能的?
当我写下面的代码时:为什么这在C#中是不可能的?,c#,.net,generics,C#,.net,Generics,当我写下面的代码时: public interface IDoSomething<in TFrom> { void Process(TFrom content, string path); void Process<TTemplate>(TFrom content, TTemplate template, string path); } public class ConcreteWorkA<str
public interface IDoSomething<in TFrom>
{
void Process(TFrom content, string path);
void Process<TTemplate>(TFrom content, TTemplate template, string path);
}
public class ConcreteWorkA<string> : IDoSomething<string>
{
public void Process(string content, string path)
{
throw new NotImplementedException();
}
public void Process<TTemplate>(string content, TTemplate template, string path)
{
throw new NotImplementedException();
}
}
公共接口
{
作废处理(从内容、字符串路径中读取);
作废流程(内容、模板模板、字符串路径);
}
A:我有什么事
{
公共作废进程(字符串内容、字符串路径)
{
抛出新的NotImplementedException();
}
公共作废流程(字符串内容、TTemplate模板、字符串路径)
{
抛出新的NotImplementedException();
}
}
它不会在下行编译的地方编译
public class ConcreteWorkB<String> : IDoSomething<String>
{
public void Process(String content, string path)
{
throw new NotImplementedException();
}
public void Process<TTemplate>(String content, TTemplate template, string path)
{
throw new NotImplementedException();
}
}
公共类混凝土工程b:idoothing
{
公共作废进程(字符串内容、字符串路径)
{
抛出新的NotImplementedException();
}
公共作废流程(字符串内容、TTemplate模板、字符串路径)
{
抛出新的NotImplementedException();
}
}
我也知道,public class-ConcreteWorkB:I有些东西是正确的,但下面的代码是有效的
public class COncreteWorkC<DataTable> : IDoSomething<DataTable>// Datatable from System.Data
{
public void Process(DataTable content, string path)
{
throw new NotImplementedException();
}
public void Process<TTemplate>(DataTable content, TTemplate template, string path)
{
throw new NotImplementedException();
}
}
公共类COncreteWorkC:IDOSthing//System.Data中的Datatable
{
公共作废进程(数据表内容、字符串路径)
{
抛出新的NotImplementedException();
}
公共作废流程(数据表内容、TTemplate模板、字符串路径)
{
抛出新的NotImplementedException();
}
}
因为string是string的别名,所以我希望它能工作。这也是为什么行为上的差异。
我使用的是VS2019,.NET5
我得到的错误是
应为语法错误“,”
应为标识符
编辑:注释和接受的答案解释字符串/数据表被视为泛型类型参数,而不是具体类型,其中as String就是错误所在。这是您的实际代码吗?如果是这样的话,那么您需要一个我期望的类,可能还值得在该类的类型中添加'in'关键字:
public interface IDoSomething<in TSource> : IDisposable{}
public class DoesSomething<in string> : IDoSomething<string>
{
public void Dispose()
{
}
}
公共接口IDoSomething:IDisposable{}
公共类做方法:我做某事
{
公共空间处置()
{
}
}
似乎是一个有趣的案例,说明什么是允许的泛型参数类型名称。
这:
没有多大意义,因为它试图引入一个具体类型(string
)作为参数名,其中只允许使用新名称
这里唯一有趣的是,它实际上在泛型参数类型名与现有类型名发生冲突时起作用。看起来编译器允许这样做,但当然这两个String
s的含义不同
public interface IDoSomething<in TSource> : IDisposable { }
class DoesSomething<String> : IDoSomething<String>
{
public void Dispose()
{
}
}
public class Program
{
public static void Main()
{
DoesSomething<int> _ = new DoesSomething<int>();
}
}
公共接口IDoSomething:IDisposable{}
课堂教学方法:我做了一些事情
{
公共空间处置()
{
}
}
公共课程
{
公共静态void Main()
{
DoesMething=新的DoesMething();
}
}
IDoSomething
中的字符串
绑定到接口定义中的TSource
doesmething
中的String
引入了一个类型参数,然后该参数将由客户端提供(int
,在上面的示例中)。您希望一行doesmething:IDoSomething{}
做什么?请注意,doesmething:IDoSomething{}
也不会编译。如果您试图指定一个类声明,请说明这一点。A将非常非常有助于您的问题。@JonSkeet:doesmething
实际编译,似乎编译器将String
视为泛型参数类型名称。如果这是类doesmething:IDoSomething{}
,那么第一个字符串是泛型类型的占位符名称,因此不允许使用它,因为它会将它与。我无法100%确定您是否认为指定的类型应为string
,或者您是否知道这是泛型类型参数的名称。请参阅。你误解了class-ConcreteWorkA:idomsomething
和class-COncreteWorkC
所声明的内容。@anshu:提供一个最小的完整示例远远不是信息过载。不需要花太多时间就可以清楚地表明您正在尝试编写一个类声明。您的编辑仍然不完整,因为现在您还没有在任何地方声明IDoSomething
。请阅读我认为区别在于string
在C#语言中是一个类(尽管它只是一个别名),而string
是由.NET提供的一个类。感谢您的详细解释,这是因为字符串被视为泛型类型参数而不是具体类型。虽然代码中的类型参数没有意义,但需要理解。@Llama:实际上string
是一个类型别名System.String
是内置的.NET类型。只要String
就可以引用System.String
,假设您已经使用上面的系统或一个类型名,比如T
。这就是为什么这个案子看起来很有趣的原因。@Wiktor我想你可能没有领会我的意思。是的,它是一个别名(如我所说),但该别名类型是C#语言固有的(是的语言,不是.NET-我知道这里的行有点模糊)String
是别名类型,但它属于.NET,并且具有名称空间。关键是,您可以使用
声明删除所有,但仍然使用字符串
,因为它是语言的一部分,但您需要使用系统
才能使用字符串
(或者您可以将其引用为系统.string
)因为它不是语言的一部分。即使在命名空间之外声明一个类,也不会阻止它的名称作为泛型类型使用,因此它必须是C语言的内置类型。
class DoesSomething<T> : IDoSomething<String>
{
public void Dispose()
{
}
}
class DoesSomething<string> : IDoSomething<string>
{
public void Dispose()
{
}
}
public interface IDoSomething<in TSource> : IDisposable { }
class DoesSomething<String> : IDoSomething<String>
{
public void Dispose()
{
}
}
public class Program
{
public static void Main()
{
DoesSomething<int> _ = new DoesSomething<int>();
}
}