【问题标题】:Why this is not possible in C#? [closed]为什么这在 C# 中是不可能的? [关闭]
【发布时间】:2021-04-15 08:17:07
【问题描述】:

当我写下面的代码时:

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();
        }

    }

   

它不会在下面编译的地方编译,

     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();
        }

    }

我也知道public class ConcreteWorkB : IDoSomething&lt;String&gt; 是正确的,但下面的代码可以工作。

     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();
        }                 
    }

由于字符串是字符串的别名,我希望它能够工作。还有为什么行为上的差异。 我正在使用 VS 2019,.Net 5。

我得到的错误是

  1. 语法错误,应为“,”
  2. 需要标识符

编辑:评论和接受的答案说明 String/DataTable 被视为泛型类型参数而不是具体类型,因此字符串是错误。

【问题讨论】:

  • 你希望DoesSomething&lt;string&gt; : IDoSomething&lt;string&gt;{} 的行做什么?请注意,DoesSomething&lt;String&gt; : IDoSomething&lt;String&gt;{} 也不编译。如果您尝试指定类声明,请明确说明。 minimal reproducible example 真的会帮助你的问题。
  • @JonSkeet: DoesSomething&lt;String&gt; 实际上编译,似乎编译器将String 视为只是一个通用参数类型名称。 dotnetfiddle.net/IzSbUg
  • 如果是class DoesSomething&lt;string&gt; : IDoSomething&lt;string&gt; {},那么第一个string 是您的泛型类型的占位符名称,因此不允许使用它,因为它会与built-in type string 混淆。我不能 100% 确定您是否认为您指定类型应该是 string,或者您是否知道这是您的泛型类型参数的 name
  • 请参阅this question。您误解了 class ConcreteWorkA&lt;string&gt; : IDoSomething&lt;string&gt;class COncreteWorkC&lt;DataTable&gt; 声明的内容。
  • @anshu:提供一个最小的完整示例远非信息过载。不需要太多就可以清楚地表明您正在尝试编写类声明。您的编辑仍然不完整,因为现在您还没有在任何地方声明 IDoSomething&lt;T&gt;。请阅读codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question

标签: c# .net generics


【解决方案1】:

看起来像是一个有趣的案例,关于允许作为泛型参数类型名称的内容。 这个:

class DoesSomething<T> : IDoSomething<string>
{
    public void Dispose()
    {
    }
}

还有这个

class DoesSomething<T> : IDoSomething<String>
{
    public void Dispose()
    {
    }
}

很明显。这里T用作通用参数名。

另一方面

class DoesSomething<string> : IDoSomething<string>
{
    public void Dispose()
    {
    }
}

没有多大意义,因为它试图引入一个具体类型 (string) 作为参数名称,其中只允许使用新名称。

这里唯一有趣的是,它实际上适用于泛型参数类型名称冲突与现有类型名称。看起来编译器允许这样做,但当然给Strings 赋予不同的含义。

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&lt;String&gt; 中的String 绑定到接口定义中的TSource

DoesSomething&lt;String&gt; 中的String 引入了一个类型参数,该类型参数预计将由客户端提供(上面示例中的int)。

【讨论】:

  • 我认为区别在于string是C#语言中的built-in type(尽管它只是一个别名),而String是.NET提供的一个类。
  • 感谢您的详细解释,这是由于 String 被视为泛型类型参数而不是具体类型而导致的问题。虽然代码中的类型参数没有意义但需要理解。
  • @Llama:实际上string 是一个类型别名。 System.String 是一个内置的 .NET 类型。只要String 可以引用System.String,假设你有上面的using System 或类型名,比如T。这就是为什么这个案例看起来很有趣。
  • @Wiktor 我想你可能没有理解我的意思。是的,它是一个别名(正如我所说),但该别名类型是 C# 语言的本机(是的语言,不是 .NET - 我知道这里的线条有点模糊)。 String 是别名类型,但它属于 .NET,并且是命名空间的。关键是您可以删除所有using 声明,但仍使用string,因为它是语言的一部分,但您需要using System 才能使用String(或者您可以将其引用为System.String),因为它不是不是语言的一部分。
  • 即使在命名空间之外声明一个类也不会阻止它的名称用作泛型类型,因此它必须是 C# 语言的内置类型。
【解决方案2】:

那是你的实际代码吗?如果是这样,那么您需要一个我期望的类,它可能还值得将“in”关键字添加到它的类型:

public interface IDoSomething<in TSource> : IDisposable{}
public class DoesSomething<in string> : IDoSomething<string>
{
    public void Dispose()
    {
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 2014-10-09
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    相关资源
    最近更新 更多