странный ввод пространства имен с помощью универсальных классов C#

#c# #generics #namespaces

#c# #универсальные классы #пространства имен

Вопрос:

У меня есть программа на C # и следующая (я полагаю, новичок) проблема:

 namespace ObjectReference
{
    public class A<TypeC>
    {
        public B b;

        public void MethodA()
        {
            b = new B(this);
        }
    }
}
  

и в другом файле в том же проекте:

 namespace ObjectReference    
{    
    public class B    
    {   
        public A<TypeC> a;

        public B(A<TypeC> myObjA)    
        {    
            a = myObjA;   
        }
    }    
}
  

В файле, где определен класс A, я получаю эту ошибку в строке « b = new B(this); «: "Argument 1: cannot convert from 'ObjectReference.A<TypeC>' to 'ObjectReference.A<ObjectReference.TypeC>'" .

Я перепробовал все, я не могу решить эту проблему, и я не понимаю, почему она появляется, все классы определены внутри одного и того же пространства имен ObjectReference (то есть классы A, B и TypeC). Это похоже на то, что в классе A он считает тип класса равным ObjectReference.A<TypeC> , тогда как в классе B он считает тип равным ObjectReference.A<ObjectReference.TypeC> .

Пожалуйста, посоветуйте.

Спасибо

Комментарии:

1. Все ли в одной сборке?

2. Покажите объявление TypeC . У вас есть какие-либо инструкции в ваших файлах? using Похоже, есть два определения TypeC .

Ответ №1:

То, что вы пишете, эквивалентно этому:

 public class A<T>
{
    public B b;

    public void MethodA()
    {
        b = new B(this);
    }
}

public class B    
{   
    public A<TypeC> a;

    public B(A<TypeC> myObjA)    
    {    
        a = myObjA;   
    }
} 
  

Обратите внимание, что я написал класс A как A<T> , а не A<TypeC> как . Даже если вы ввели допустимое имя типа, это законный универсальный тип C #, поэтому в определении класса A TypeC не совпадает с классом TypeC . Отсюда и сообщение об ошибке, которое вы получаете.

Чтобы это сработало, вам нужно сделать что-то вроде этого:

 public class A<T>
{
    public B<T> b;

    public void MethodA()
    {
        b = new B<T>(this);
    }
}

public class B<T> 
{   
    public A<T> a;

    public B(A<T> myObjA)    
    {    
        a = myObjA;   
    }
}    
  

Затем вы можете вызвать код следующим образом:

 var a = new A<TypeC>();
a.MethodA();
  

Я надеюсь, что это поможет.

Ответ №2:

Вы пытаетесь указать классу B иметь конструктор, принимающий экземпляр типа A без какой-либо спецификации типа. Вы можете либо обновить класс B, приняв параметр типа, как и класс A:

 public class B<T>
{
    ...
} 
  

или вы можете сделать конструктор класса b более конкретным, указав для него параметр типа, например:

 public B(A<string> myObjA)
{
    a = myObjA;
} 
  

Для получения дополнительной информации об этом параметре типа я предлагаю вам посмотреть некоторую информацию об универсальных классах. Существует множество книг и статей!

Редактировать

Я вижу, вы обновили код. Этого все равно будет недостаточно, если TypeC не является фактическим типом, который вы нам не указали. Однако это было бы очень сложным для понимания сценарием именования. По сути, в классе A вы определяете параметр универсального типа, который может быть указан под именем TypeC, а в классе B вы предполагаете, что тип с таким именем существует. Я все же рекомендую вам немного почитать о дженериках.

Комментарии:

1. Вот TypeC, определенный, как я уже сказал, в том же проекте, в том же пространстве имен, в другом файле: namespace ObjectReference { public class TypeC { public string stringC; public TypeC() { stringC = «stringC»; } } } Поэтому я указываю параметр type в конструкторе в classB. Фрагмент, который я привел здесь, является упрощенной версией моего фактического кода, но это проблема, с которой мне нужно справиться. Я буду подробно читать о дженериках, однако я надеялся, что у кого-то есть идея о том, как это решить. Спасибо

2. @laail: Пожалуйста, добавьте эту информацию в свой вопрос и правильно отформатируйте ее.

Ответ №3:

Вы пытаетесь передать универсальную реализацию A в конструктор B, который использует нестандартную реализацию A. К сожалению, это не работает и потребует некоторого переписывания класса B.

Однако то, что сработало бы, было бы чем-то вроде:

 namespace ObjectReference
{
    public class B<TypeC>
    {
        public A<TypeC> a;

        public B(A<TypeC> myObjA) 
        {
            a = myObjA;
        }
    }
 }
  

а затем вызовите его как:

 b = new B<TypeC>(this);
  

Ответ №4:

A<TypeC> это так называемый открытый универсальный тип, который вы не можете передать в качестве аргумента метода.

Чтобы исправить это, вам также нужно сделать B generic. Использование A<TypeC> внутри B<TypeC> теперь создает A<TypeC> сконструированный открытый универсальный тип. Это просто означает, что параметр универсального типа B является «производным» от A<TypeC> .

Возможно, вы захотите взглянуть на страницу MSDN об универсальных классах в C #.

 namespace ObjectReference    
{    
    public class B<TypeC>    
    {   
        public A<TypeC> a;

        public B(A<TypeC> myObjA)    
        {    
            a = myObjA;   
        }
    }    
}