Как я могу создавать временные объекты для передачи без явного создания класса?

Мне часто приходится создавать класс в качестве контейнера для некоторых данных. Он используется ненадолго, но мне все еще нужно создать класс. Как это:

public class TempObject
{
    public string LoggedInUsername { get; set; }
    public CustomObject SomeCustomObject { get; set; }
    public DateTime LastLoggedIn { get; set; }
}


public void DoSomething()
{
    TempObject temp = new TempObject
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah blah,
        LastLoggedIn = DateTime.Now
    };
    DoSomethingElse(temp);
}

public void DoSomethingElse(TempObject temp)
{
    // etc...
}

Обычно мои временные объекты имеют намного больше свойств, поэтому я хочу сгруппировать их в первую очередь. Я бы хотел, чтобы был более простой способ, например, с анонимным типом. Проблема в том, что я не знаю, что принимать, когда я передаю это другому методу. Тип анонимный, так как я должен принять его на другой стороне?

public void DoSomething()
{
    var temp = new
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah,
        LastLoggedIn = DateTime.Now
    };
    // I have intellisense on the temp object as long as I'm in the scope of this method.
    DoSomethingElse(temp);
}

public void DoSomethingElse(????)
{
    // Can't get my anonymous type here. And even if I could I doubt I would have intellisense.
}

Есть ли лучший способ создать временный контейнер для множества разных типов или мне нужно определять классы каждый раз, когда мне нужен временный объект для группировки?

Заранее спасибо.


person Chev    schedule 10.08.2011    source источник
comment
Для этого существует библиотека с открытым исходным кодом, проверьте это и этот пост. надеюсь кому-нибудь поможет.   -  person Shaiju T    schedule 06.05.2017
comment
Вы можете использовать модификатор internal для вашего TempObject и связанных членов вместо общедоступных, таким образом, этот тип не будет доступен из других сборок.   -  person Lorenzo Delana    schedule 20.08.2020


Ответы (5)


Tuple может быть решением, которое вы ищете.

public void DoSomething() 
{
    var temp = Tuple.Create("test", "blah blah blah", DateTime.Now);
    DoSomethingElse(temp);
}

public void DoSomethingElse(Tuple<string, string, DateTime> data)
{
    // ...
}
person Jacob    schedule 10.08.2011
comment
Интересный. Да, это было бы больше похоже на то, что я ищу. - person Chev; 11.08.2011
comment
KeyValuePair до .NET 4.0, хотя он позволяет вам иметь только двух «участников». - person Dmitry; 11.08.2011
comment
Я иду с этим ответом, потому что это действительно именно то, о чем я просил. Однако на самом деле я не собираюсь его использовать, потому что, применив его на практике, я решил, что он не очень читаем. Создание пользовательского объекта передачи всегда хорошо названо и легко читается для любого, кто изучает код. Я могу когда-нибудь найти применение для Tuple, но небольшие накладные расходы на класс просто облегчают отслеживание и запоминание. - person Chev; 11.08.2011
comment
Отличный ответ, я думаю. Как в DoSomethingElse получить доступ к отдельным компонентам кортежа? - person paparazzo; 11.08.2011
comment
Для этого существует библиотека с открытым исходным кодом, проверьте это и этот пост. надеюсь кому-нибудь поможет. - person Shaiju T; 06.05.2017

В правилах указано, что

Вы не можете объявить поле, свойство, событие или возвращаемый тип метода как имеющие анонимный тип. Точно так же вы не можете объявить формальный параметр метода, свойства, конструктора или индексатора как имеющий анонимный тип.

Лично я бы просто стиснул зубы, чтобы сохранить целостность времени компиляции.

person Neil Moss    schedule 10.08.2011
comment
Ах, но кортеж Джакбо довольно милый! - person Chev; 11.08.2011
comment
Это так, пока вы не забудете порядок параметров вашего кортежа. - person Neil Moss; 11.08.2011
comment
Правда, var newTuple = new Tuple<int,int,string,DateTime,int,bool>(1,2,"hello",DateTime.Now, 3, true); немного некрасивый. - person Chev; 11.08.2011
comment
Хотя мой ответ использует Tuple и работает, я бы также рекомендовал этот ответ, поскольку код легче читать и он менее подвержен ошибкам кодирования. - person Jacob; 11.08.2011
comment
@Jacob, верно, но на самом деле это не ответ, поскольку создание реальных объектов - это то, чем я уже занимаюсь. - person Chev; 11.08.2011

Кортеж — это чистый путь, но просто чтобы вы знали, что C# не подведет даже в противном случае, и чтобы ответить на вопрос, вот как может выглядеть DoSomethingElse:

private static void DoSomething(object temp)
        {
            var typedTemp = CastToType(temp, new
                            {
                                LoggedInUsername = "dummy",
                                SomeCustomObject = "dummy",
                                LastLoggedIn = DateTime.Now
                            });

            Console.WriteLine(typedTemp.LastLoggedIn);
        }

private static T CastToType<T>(object obj, T type)
        {
            return (T) obj;
        }

PS: Не -1, я не буду использовать это, я не прошу вас использовать это :)

person manojlds    schedule 10.08.2011
comment
Я не собираюсь -1 или что-то в этом роде, но это пока один из худших вариантов. смешной! - person Chev; 11.08.2011
comment
@Alex Ford - Как я уже сказал, просто говорю, что есть способ! - person manojlds; 11.08.2011

Вы можете обойти анонимные типы, объявив параметр динамическим в C# 4. Тем не менее, я бы не рекомендовал это делать, кроме как в закрытых методах. Вы теряете безопасность типов, IntelliSense и удобочитаемость.

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

Лично я бы создал класс. Посмотрите, есть ли абстракция, которая охватывает все ваши типы, и объявите ее как интерфейс, а затем используйте универсальный контейнер этого типа.

person TrueWill    schedule 10.08.2011
comment
Я знаю о динамическом ключевом слове, но это полностью убирает intellisense и удаляет проверку типов во время компиляции. Если бы он был динамическим, я мог бы получить доступ к temp.NonExistentProperty и не получил бы ошибки компилятора. Это абсолютно ужасно. - person Chev; 11.08.2011
comment
@Alex: я согласен, поэтому я не рекомендую его для этого использования. Но смысл tuple.Item1 не очевиден для читателя, так что это тоже имеет свои недостатки. - person TrueWill; 11.08.2011
comment
Я тоже согласен. Сначала Tuple казался идеальным, но я начинаю менять свое мнение ради удобочитаемости. - person Chev; 11.08.2011
comment
@Alex Алекс, если вы хотите, чтобы компилятор мог проверять типы, то как вы ожидаете, что он это сделает, если вы не предоставите класс? - person paparazzo; 11.08.2011
comment
@BalamBalam Скажите, как вы думаете, почему я разместил этот вопрос? А) я уже знал ответ или Б) я не знал ответа. У тебя есть 30 секунд... иди. ---играет музыкальную тему об опасности--- - person Chev; 11.08.2011

    public class GenericObjs
    {
        private List<object> objs = new List<object>();
        public List<object> Objs { get { return objs; } set { objs = value; } }
        public GenericObjs(List<object> Objs) { objs = Objs; }
    }

Вы можете включить строку списка и конструктор для строки списка...

Я просто не вижу необходимости в одноразовых занятиях. Если бизнес-объект имеет структуру, то класс — это способ определить и обеспечить соблюдение этой структуры, и это не так много кода.

person paparazzo    schedule 10.08.2011
comment
Это противоречит принципам строго типизированного языка, и есть гораздо лучшие подходы. поместите все в коллекцию объектов, ура. - person MHolzmayr; 14.04.2016
comment
@MHolzmayr Вопрос заключается в передаче временных объектов. - person paparazzo; 14.04.2016