Как переопределить этот метод, используя «где T: объект»

Я пытаюсь переопределить этот метод, но не понимаю, как

public virtual TUserData GetCurrentUser<TUserData>() where TUserData : UserData
        {
            LoadTokenCookie(String.Empty);

            if (!IsCurrentUserAuthorized())
            {
                return null;
            }

            string responseText = (OAuthVersion == "1.0")
                            ? ExecuteAuthorizedRequest(HttpMethod.GET, MeGraphEndpoint)
                            : string.IsNullOrEmpty(AccessToken)
                                ? ExecuteWebRequest(HttpMethod.GET, new Uri(MeGraphEndpoint + "?" + "access_token=" + AuthToken), null, String.Empty)
                                : ExecuteWebRequest(HttpMethod.GET, new Uri(MeGraphEndpoint + "?" + AccessToken + "=" + AuthToken), null, String.Empty);
            var user = Json.Deserialize<TUserData>(responseText);
            return user;
        }

Когда я делаю следующее,

public override TUserData GetCurrentUser<TUserData>() where TUserData : UserData{


            return new UserData();
        }

компилятор выдает "Ограничения для методов переопределения и явной реализации интерфейса наследуются от базового метода, поэтому их нельзя указать напрямую"

Поэтому я предположил, что тип возвращаемого значения по своей сути будет пониматься как UserDat, а не как TUserData, но следующее утверждает, что тип возвращаемого значения неверен.

public override TUserData GetCurrentUser<TUserData>(){


                return new UserData();
            }

person Mark Hollas    schedule 09.01.2016    source источник
comment
Пожалуйста, покажите свой класс наследования   -  person Bubba    schedule 09.01.2016
comment
Вы уверены, что компилятор С# выдает исключение?   -  person 15ee8f99-57ff-4f92-890c-b56153    schedule 09.01.2016
comment
Вы намерены использовать CreateCurrentUser‹› с несколькими типами UserData, или есть только один тип, который вы ожидаете вернуть из этого вызова метода (как предполагает ваша реализация)?   -  person alexm    schedule 09.01.2016


Ответы (4)


В методе переопределения следующие работы.

public override TUserData GetCurrentUser<TUserData>()
{
    return default(TUserData);
}    

Если компилятор позволяет вам написать следующий код (UserDataA является подклассом UserData)

public override TUserData GetCurrentUser<TUserData>()
{
    return new UserDataA();
}   

Затем потребитель этого класса вызывает этот метод следующим образом (UserDataB — еще один подкласс UserData)

var userDataB = GetCurrentUser<UserDataB>();

Потребитель ожидает экземпляр типа UserDataB. Но метод возвращает экземпляр типа UserDataA. всё портится.

Таким образом, в универсальном методе TUserData представляет тип, с которым вы имеете дело. Вы можете вернуть только экземпляр этого конкретного типа, отличного от любого другого типа.

person Colin    schedule 09.01.2016

Вы должны использовать имя, которое вы использовали в наследующем классе. Вы не указали класс, поэтому позвольте мне привести пару примеров. Если ваш наследующий класс выглядит так:

public class ABC<T> extends DEF<T> {

Тогда ваша функция переопределения должна использовать тот же T

public override TGetCurrentUser<T>() where T: UserData{

Если вы указали тип, вам нужно использовать этот тип

public class ACB extends DEF<SomeUserData> {
    public override SomeUserDataGetCurrentUser<SomeUserData>(){
person PearsonArtPhoto    schedule 09.01.2016

По сути, вы пытаетесь преобразовать UserData в любой тип TUserData, что недопустимо. Поскольку вы не можете перегрузить метод, просто изменив тип возвращаемого значения, вы не можете перегрузить метод. Вам придется использовать новый неуниверсальный метод и/или создать метод преобразования, который может преобразовать UserData в TUserData.

person D Stanley    schedule 09.01.2016

where TUserData : UserData означает, что TUserData может быть UserData или любым классом, унаследованным от UserData.

Вы возвращаете new UserData(), который не всегда можно преобразовать в TUserData.

Например, рассмотрим этот класс, который наследуется от UserData:

public class UserData2 : UserData
{

}

Что происходит, когда вы звоните GetCurrentUser<UserData2>()?

Система не может преобразовать new UserData() в UserData2.

Что вы можете сделать, так это добавить ограничение, что TUserData имеет конструктор без параметров, например:

public virtual TUserData GetCurrentUser<TUserData>() where TUserData : UserData, new()
{

}

А затем сформируйте производный класс, вы можете построить TUserData следующим образом:

public override TUserData GetCurrentUser<TUserData>()
{
    return new TUserData();
}

Это, конечно, означает, что вы можете вызывать GetCurrentUser<TUserData>() для UserData производных классов, которые имеют конструкторы без параметров.

person Yacoub Massad    schedule 09.01.2016