0

I have created a factory class called AlarmFactory as such...

1    class AlarmFactory
2    {
3        public static Alarm GetAlarm(AlarmTypes alarmType)  //factory ensures that correct alarm is returned and right func pointer for trigger creator.
4        {
5            switch (alarmType)
6            {
7                case AlarmTypes.Heartbeat:
8                    HeartbeatAlarm alarm = HeartbeatAlarm.GetAlarm();
9                    alarm.CreateTriggerFunction = QuartzAlarmScheduler.CreateMinutelyTrigger;
10                    return alarm;
11
12                   break;
13                default:
14                
15                    break;
16            }
17        }
18    }

Heartbeat alarm is derived from Alarm. I am getting a compile error "cannot implicitly convert type...An explicit conversion exists (are you missing a cast?)". How do I set this up to return a derived type?

EDIT

THANK YOU ALL FOR YOUR ANSWERS. I fixed the compile error within ten minutes which is why i did not post the whole error. But I appreciated the different approaches that were mentioned.

For the record it was "Cannot implicitly convert type 'goAlarmsCS.HeartbeatAlarm' to 'goAlarmsCS.Alarm' An explicit conversion exists (are you missing a cast?)". (I think.) The error was occurring on line 8.

Seth

4

4 に答える 4

4

以下は、HeartbeatAlarm オブジェクトを取得する特定の GetHeartbeatAlarm 関数と、ジェネリック パラメータによってタイプが決定されるアラームを返すジェネリック GetAlarm 関数を含むソリューションです。下部には、これがどのように呼び出されるかを示すコード例がいくつかあります。

enum AlarmTypes
{
    Heartbeat,
    AnotherAlarm,
    // ...
}

delegate void CreateTriggerDelegate();

class Alarm
{
    // ...

    public CreateTriggerDelegate CreateTriggerFunction { get; set; }
}

class HeartbeatAlarm : Alarm
{
    // ...

    public static HeartbeatAlarm GetAlarm()
    {
        return new HeartbeatAlarm();
    }
}

class QuartzAlarmScheduler
{
    public static CreateTriggerDelegate CreateMinutelyTrigger { get; set; }
}

class AlarmFactory
{
    public static Alarm GetAlarm(AlarmTypes alarmType)  //factory ensures that correct alarm is returned and right func pointer for trigger creator.
    {
        switch (alarmType)
        {
            case AlarmTypes.Heartbeat:
                return GetHeartbeatAlarm();
            default:
                throw new ArgumentException("Unrecognized AlarmType: " + alarmType.ToString(), "alarmType");
        }
    }

    static Alarm _GetAlarm<T>()
        where T : Alarm
    {
        Type type = typeof(T);
        if (type.Equals(typeof(HeartbeatAlarm)))
            return GetHeartbeatAlarm();
        else
            throw new ArgumentException("Unrecognized generic Alarm argument: " + type.FullName, "T");
    }

    public static T GetAlarm<T>()
        where T : Alarm
    {
        return (T)_GetAlarm<T>();
    }

    public static HeartbeatAlarm GetHeartbeatAlarm()
    {
        HeartbeatAlarm alarm = HeartbeatAlarm.GetAlarm();
        alarm.CreateTriggerFunction = QuartzAlarmScheduler.CreateMinutelyTrigger;
        return alarm;
    }
}

class Example
{
    static void GetAlarmExamples()
    {
        HeartbeatAlarm alarm;

        alarm = AlarmFactory.GetHeartbeatAlarm();

        alarm = AlarmFactory.GetAlarm<HeartbeatAlarm>();

        alarm = (HeartbeatAlarm)AlarmFactory.GetAlarm(AlarmTypes.Heartbeat);
    }
}
于 2010-06-02T20:15:23.387 に答える
3

あなたの最善の策はAlarm、インターフェイスを作成するか、それが不可能な場合はインターフェイスを作成しIAlarm、このインターフェイスから と の両方を継承することAlarmですHeartbeatAlarm

AlarmFactory.GetAlarmインスタンスを返す必要がありIAlarmます。同様に、インスタンスHeartbeatAlarm.GetAlarm()を返す必要があります。IAlarm

これにより、コンパイラ エラーが解消されます。さらに、すべての関係が明確に契約に基づいているため、コードがより将来に適したものになるはずです。

于 2010-06-02T19:36:22.063 に答える
0

一部の人がすでに示唆しているように、冗長インターフェイスはこれを実現する簡単な方法です。きれいな例は、将来の訪問者に役立つようです..

public interface IAlarm
{
    public int bpm { get; set; }    // declared base props
}

public class Alarm : IAlarm
{
    public int bpm { get; set; }    // implemented base props
}

public class HeartbeatAlarm : Alarm
{
    public int min { get; set; }    // extended type specific props
}

public class FactoryMethods
{
    public static T AlarmFactory<T>(int bpm) where T : IAlarm, new()
    {
        // interfaces have no constructor but you can do this
        T alarm = new T() {
            bpm = bpm
        };

        return alarm;
    }
}

// C# will automagically infer the type now..
HeartbeatAlarm heartbeatAlarm = FactoryMethods.AlarmFactory<HeartbeatAlarm>(40);
于 2015-04-03T02:10:39.133 に答える
0

コンパイラが提案することを試しましたか?

return (Alarm) alarm;

編集:これは完全に間違っていますが、コメントでの議論を維持するために、この回答をここに残しておきます。

于 2010-06-02T19:29:49.223 に答える