2

我在尝试使Func<T>表达式评估对象实例中的属性时遇到了一些困难,例如

var t = new Transition<ILexeme>( 1, () => TokenType == eToken.TOKEN_COMMENT );

Visual Studio 编译器抱怨非静态字段、方法或属性“ILexeme.TokenType.get”错误需要对象引用,因为它需要一个ILexeme对象实例。

我正在尝试做的是创建一个状态机,用于Func<T>调用转换函数的委托,该委托会测试该eToken属性的值是否与eToken令牌流中的值匹配。如果相等,则机器进入下一个状态。

问题是我ILexeme作为泛型类型传入Transition类,但我希望转换函数使用泛型类型中的属性,即TokenType. 我的问题是如何实现这一点,记住它必须适用于值类型,即char,int等?

以下是 ILexeme 的定义:

public interface ILexeme
{
    eToken TokenType { get; }
    String TokenString { get; }
}

这是ILexeme的具体实现:

public enum eToken : int
{
    TOKEN_COMMENT,
    TOKEN_SEPARATOR
}

public class Token : ILexeme
{
    public eToken TokenType { get; }
    public String TokenString { get; }
}

这是过渡的定义:

public readonly int FromState;
public readonly int ToState;
public readonly Func<T> Input;

public Transition( int fromState, Func<T> input, int toState )
{
    this.FromState = fromState;
    this.ToState = toState;
    this.Input = input;
}
4

3 回答 3

2

在您的Transition<ILexeme>-constructor 中,您期望 aFunc<ILexeme>但您提供 a Func<bool>

于 2012-11-20T14:46:50.817 回答
2

我认为你写错了你的 lambda 表达式。由于TokenType是实例属性,因此您应该将对象的实例传递给 lambda。现在它是无参数的。所以,我认为它应该是这样的

var t = new Transition<ILexeme>( 1, eTok => eTok.TokenType == eToken.TOKEN_COMMENT );

和过渡班

public readonly int FromState;
public readonly int ToState;
public readonly Func<T, bool> Input;

public Transition( int fromState, Func<T, bool> input, int toState )
{
    this.FromState = fromState;
    this.ToState = toState;
    this.Input = input;
}

此外,您可能希望将第二个类型参数引入Transition类,因此它变得非常普遍:

class Transition<TInput, TResult> {
public readonly int FromState;
public readonly int ToState;
public readonly Func<T, TResult> Input;

public Transition( int fromState, Func<T, TResult> input, int toState )
{
    this.FromState = fromState;
    this.ToState = toState;
    this.Input = input;
}
}

如果是这种情况,您可能希望使用where 子句放置一些类型约束。

于 2012-11-20T14:48:48.647 回答
1

您得到的错误是因为 TokenType 是类型 ILexeme 的属性,但是在您对构造函数的调用中没有该类型的有效实例。也许你希望你的声明是

public Transition(int fromState, Func<T, bool>, int toState) { /* ... */ }

然后你可以把你的代码写成:

var t = new Transition<ILexeme>(1, lex => lex.TokenType == eToken.TOKEN_COMMENT, 2);
于 2012-11-20T14:55:22.823 回答